如何在C# Linq中按客户与产品双字段分组统计数据?
问题分析与解决方案
你的需求是按**客户(User)和产品(Product)**分组,统计每个客户对应每个产品的总销售数量与总金额,原代码存在以下核心问题:
- 分组后使用
SelectMany(x => x)展开分组,完全抵消了分组的作用,无法得到聚合后的统计结果 - 未处理导航属性的null值(如
Sale、Sale.User或Product可能为null),会触发空引用异常 Include语句冗余,EF Core在使用Select投影时会自动加载所需关联数据,无需显式声明
正确实现代码
以下是null安全且符合需求的分组统计代码:
var saleStats = await context.SaleItems // 过滤关联数据为空的记录,避免空引用异常 .Where(x => x.Sale != null && x.Sale.User != null && x.Product != null) // 按用户+产品的唯一组合分组,同时保留需要展示的名称字段 .GroupBy(x => new { UserId = x.Sale.User.Id, UserName = x.Sale.User.Name ?? "未知用户", ProductId = x.Product.Id, ProductName = x.Product.Name }) // 对每个分组聚合计算总数量和总金额 .Select(group => new { group.Key.UserId, group.Key.UserName, group.Key.ProductId, group.Key.ProductName, TotalCount = group.Sum(item => item.Count), TotalPrice = group.Sum(item => item.Product.Price * item.Count) }) .ToListAsync();
可选:使用自定义DTO接收结果
如果需要将结果绑定到业务模型而非匿名类型,可以定义一个统计类:
public class UserProductSaleStats { public long UserId { get; set; } public string UserName { get; set; } public int ProductId { get; set; } public string ProductName { get; set; } public int TotalCount { get; set; } public decimal TotalPrice { get; set; } }
然后修改Select部分:
.Select(group => new UserProductSaleStats { UserId = group.Key.UserId, UserName = group.Key.UserName ?? "未知用户", ProductId = group.Key.ProductId, ProductName = group.Key.ProductName, TotalCount = group.Sum(item => item.Count), TotalPrice = group.Sum(item => item.Product.Price * item.Count) })
内容的提问来源于stack exchange,提问作者Poppy Field
相关产品推荐
相关产品推荐

