You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在C# Linq中按客户与产品双字段分组统计数据?

问题分析与解决方案

你的需求是按**客户(User)和产品(Product)**分组,统计每个客户对应每个产品的总销售数量与总金额,原代码存在以下核心问题:

  1. 分组后使用SelectMany(x => x)展开分组,完全抵消了分组的作用,无法得到聚合后的统计结果
  2. 未处理导航属性的null值(如Sale、Sale.User或Product可能为null),会触发空引用异常
  3. 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.25 12:21:28