EF Core聚合查询将计算下推至数据库执行,需用Count()、Sum()、Avg()等方法生成对应SQL;分组聚合用GroupBy+Select保持IQueryable;注意null处理及类型匹配,避免.ToList()导致内存计算。

EF Core 的聚合查询本质是把计算逻辑下推到数据库执行,而不是在内存里遍历。用对方法,才能既准确又高效。
常用聚合方法怎么写
直接调用 Count()、Sum()、Avg() 等扩展方法,它们会生成 SQL 的对应聚合函数:
-
Count():统计行数,
context.Orders.Count()→SELECT COUNT(*) FROM Orders -
Count(x => x.Status == "Shipped"):带条件计数,生成
COUNT(CASE WHEN ... THEN 1 END) - Sum(x => x.Amount):只支持数值类型字段,null 值自动忽略
- Avg(x => x.Rating):同理,字段为 null 的记录不参与计算
- Max(x => x.CreatedAt) 或 Min(x => x.Price):支持日期、数字、字符串(按字典序)
分组后聚合更实用
单表聚合往往不够,多数业务需要“按某维度分组再算总数/平均值”。EF Core 支持链式 GroupBy + Select:
context.Orders.GroupBy(o => o.CustomerId).Select(g => new { Id = g.Key, Total = g.Sum(o => o.Amount) })- 结果是 IQueryable,仍走数据库,不会把全部订单拉到内存
- 可嵌套多个聚合:
g.Average(o => o.Quantity)、g.Count()同时用
注意 null 和类型陷阱
聚合行为和数据库一致,但容易踩坑:
-
Count(x => x.Name) 统计的是
Name IS NOT NULL的行数,不是总行数 - Sum() 和 Avg() 遇到非数值类型字段(比如 string),运行时报错或返回 0(取决于 provider)
- Max()/Min() 对字符串字段,按字母顺序比较,不是按长度
- 想统计所有行(含 null),用 Count() 不带参数;想统计某列非空行,才传表达式
避免常见性能错误
聚合必须保持在服务端执行,否则失去意义:
- ❌ 错误:先
.ToList()再.Sum()→ 全量查出再内存计算 - ✅ 正确:所有聚合操作前不触发枚举,保持
IQueryable状态 - 调试时可用
context.Orders.ToQueryString()(EF Core 7+)看生成的 SQL
基本上就这些。写对表达式,看清字段类型,让数据库干活,别自己搬数据。










