Linq group by 与返回计数

Posted

技术标签:

【中文标题】Linq group by 与返回计数【英文标题】:Linq group by with return count 【发布时间】:2020-11-03 22:14:48 【问题描述】:

Net 核心和 Linq。我有如下表

订单表

OrderId   Status
1         New
2         New
3         In Progress
4         In Progress
5         Closed
6         Closed

我有以下型号

public class SummaryEntity
  
  public int New  get; set; 
  public int InProgress  get; set; 
  public int Closed  get; set; 
 

然后我需要返回并绑定到下面的模型,如下所示

New : 2
InProgress : 2
Closed : 2 

我尝试过类似下面的方法

SummaryEntity result = (from item in Orders
                          group item by new  item.Status  into g
                          select new SummaryEntity //not sure how to get count and assign it to model 
                           );

我发现很难对模型进行分组和赋值。有人可以帮我写查询。任何帮助,将不胜感激。谢谢

【问题讨论】:

SummaryEntity 是单类,您想如何将其转换为列表?看来,计算 3 次会更好 嗨对不起我的错误,已删除 toList() Orders.Count(o => o.Status == "New") 和其他状态相同。另外,为什么 count 是string 嗨,帕维尔,哪个算?我找不到它 是的 pavel 我改成 int 你是对的 【参考方案1】:

您已经按状态对项目进行了分组,因此g.Key 将包含状态值,g 本身就是分组项目的可枚举。如果你想计算他们的数量,请使用Count(),例如:

var counts = from item in Orders
             group item by new  item.Status  into g
             select new status=g.Key, count=g.Count();

这将为每个状态值返回一个对象及其计数。为每个状态获取不同的列本质上是旋转,将行转换为列。

但在这种情况下,如果您事先知道状态名称,您可以将结果转换为字典并按名称检索计数,例如:

var dict=counts.ToDictionary(x=>x.status,x=>x.count);

var model= new SummaryEntity 
           
               New        = dict.TryGetValue("New",out var c_n)
                            ? c_n : 0,
               InProgress = dict.TryGetValue("InProgress",out var c_p)
                            ? c_p : 0,
               Closed     = dict.TryGetValue("Closed",out var c_c)
                            ? c_c : 0,
           ;

Dictionary.TryGetValue 用于在缺少状态值时避免异常

【讨论】:

非常好。您可以使用ToLookup 简化此操作,如var byStatus = Orders.ToLookup(o => o.Status);,然后您可以编写new SummaryEntity New = byStatus["New"].Count(), ... @AluanHaddad 这不会简化查询,它会延迟计数计算。如果 OP 使用 EF,GroupBy 将只返回状态值和计数,而ToLookup 将返回所有项目并将计数计算留给.Count() 我的意思是简化代码,因为您不需要检查密钥。你总是可以Orders.ToLookup(o => o.Status, o => o.OrderId);【参考方案2】:

你的模型没有意义。您只有状态不是 New、InProgress、Closed。尝试以下:

            DataTable dt = new DataTable();
            dt.Columns.Add("OrderId", typeof(int));
            dt.Columns.Add("Status", typeof(string));
            
            dt.Rows.Add( new object[]  1, "New");
            dt.Rows.Add( new object[]  2, "New");
            dt.Rows.Add( new object[]  3, "In Progress");
            dt.Rows.Add( new object[]  4, "In Progress");
            dt.Rows.Add( new object[]  5, "Closed");
            dt.Rows.Add( new object[]  6, "Closed");

            var results = dt.AsEnumerable()
                .GroupBy(x => x.Field<string>("Status"))
                .Select(x => new  status = x.Key, count = x.Count() )
                .ToList();

【讨论】:

嗨,感谢您的回答,但我需要将其分配给模型,例如,如果状态 New 为零,那么我想返回 New:0 您的模型是字符串而不是整数。然后你需要在数据库中创建一个链接到你的模型的表

以上是关于Linq group by 与返回计数的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 LINQ group by 子句返回唯一的员工行?

C# Linq to sql 实现 group by 统计多字段 返回多字段

Linq Group by 并获取返回所有列的特定字符串规则的所有值

3-实体数据模型与LINQ-分组

C# Linq to SQL — Group by

LINQ to SQL语句之Group By/Having