如何使用动态 linq 核心 select 并根据另一个字段的条件进行计数

How to select and count base on a condition of another field using dynamic linq core

我正在使用 Entity FrameworkDynamic Linq Core 在 运行 时间执行一些动态查询.我有一个关于如何编写动态 linq 语句来输出计数列的问题,其中每列是另一个字段的字段项。

假设我有一个包含 3 列的 table:ID、性别和年龄(假设它们只有 10 多岁)。

ID | Gender | Age
01 |   male |  20
02 | female |  30
... some thousands of rows

我想按年龄段统计每个性别(groupBy Gender)的人数。

[{Gender:"male", "20": 120, "30": 200, "40": 300},
{Gender:"female", "20": 300, "30": 200, "40": 1000 }]

我试着按年龄分组,但这并没有给出我想要的上述格式,因为每个性别和年龄组合都会成为一个新的数组项。

var query = db.someDB
        .GroupBy("new(Gender, Age)")
        .Select("new(Key.Gender as Gender, Key.Age as Age, Count() as value)");

我被限制使用动态 linq 核心,因为在我的实际应用程序中,性别和年龄字段由用户决定,因此他们的字段名称将在 运行 时更改。

你会怎么做?

假设您的查询 returns 以下对象的列表 class

public class Data {
 public string Gender { get; set;}
 public int Age { get; set;}
 public int Value { get; set;}
}
  Data results = //query result

  var resultsV2 = results.GroupBy(r => r.Gender);
      
  var list = new List<IDictionary<string, object>>();

  foreach(var g in resultsV2)
  {
    IDictionary<string, object> obj = new ExpandoObject();

    var data = g.Select(x => x);
    obj["Gender"] = $"{g.Key}";
        
    foreach(var d in data)
    {
      var propName = $"{d.Age}";
      obj[propName] = $"{d.Value}";
    }

    list.Add(obj);

  }

  string jsonString = JsonConvert.SerializeObject(list);

Fiddler

输入:

new List<Data>
{
  new Data() { Gender = "Male", Age = 20, Value = 5 },
  new Data() { Gender = "Male", Age = 30, Value = 3 },
  new Data() { Gender = "Female", Age = 20, Value = 9 }
};

输出:

[{"Gender":"Male","20":"5","30":"3"},{"Gender":"Female","20":"9"}]

您可以在 LINQ 查询中利用 JSON.Net 类型。 JObject accepts an collection of JProperty and JArray 接受对象集合。这些可以在一个 LINQ 查询中构建:

var table = new List<Person>{
        new Person(30,"M"),
        new Person(30,"M"),
        new Person(30,"M"),
        new Person(20,"M"),
        new Person(40,"M"),
        new Person(30,"V"),
        new Person(50,"V"),
        new Person(50,"V")
    };
    
    var data = 
        from p1 in table
        group p1 by p1.Gender into genderGrp  
        // Build our JObject
        select new JObject( 
            new JProperty( "Gender", genderGrp.Key)
            // and the rest of proprties will the collection of Age
            , (  from p2 in genderGrp            // over the gender
                 group p2 by p2.Age into ageGrp
                 select new JProperty(
                     ageGrp.Key.ToString()  // needs to be a string
                   , ageGrp.Count()))       // aggregate count
       );
             
    var jtoken = new JArray(data);  // the collection of JObjects goes in the JArray
    Console.WriteLine(jtoken.ToString());

结果将是:

[
  {
    "Gender": "M",
    "30": 3,
    "20": 1,
    "40": 1
  },
  {
    "Gender": "V",
    "30": 1,
    "50": 2
  }
]