LINQ按ProductId分组查询获取产品名称及总销量的报错咨询
报错原因
你遇到的InvalidOperationException异常根本原因是 Entity Framework(EF/EF Core)无法将分组后直接调用的First()方法翻译为对应的SQL语句,因此无法在数据库侧执行该逻辑,进而抛出异常。
另外需要注意你的代码中prdouctname为拼写错误,建议修正为productname。
正确实现方案
方案1:使用复合分组键(最推荐)
正常业务逻辑中同一个ProductId对应的ProductName是固定的,因此可以将两个字段共同作为分组键,直接从分组的Key属性中取值,EF可完美翻译为SQL,全程在数据库侧执行,性能最优:
var query = from saleorder in _dbContext.SaleOrderDetail group saleorder by new { saleorder.ProductId, saleorder.ProductName } into salesummary select new { productid = salesummary.Key.ProductId, productname = salesummary.Key.ProductName, totalqty = salesummary.Sum(s => s.Quantity) };
方案2:使用聚合函数取ProductName
如果不想修改分组键,可以利用Max/Min聚合函数取值,同一个ProductId下所有的ProductName都相同,所以聚合返回的结果完全正确,同样可以被EF翻译为SQL执行:
var query = from saleorder in _dbContext.SaleOrderDetail group saleorder by saleorder.ProductId into salesummary select new { productid = salesummary.Key, productname = salesummary.Max(s => s.ProductName), totalqty = salesummary.Sum(s => s.Quantity) };
方案3:内存侧执行分组后操作(仅适合小数据量场景)
如果数据量非常小,可以先将数据加载到内存后再执行First()操作,此时不需要EF翻译方法:
var query = _dbContext.SaleOrderDetail .GroupBy(s => s.ProductId) .AsEnumerable() // 后续逻辑切换到内存执行 .Select(salesummary => new { productid = salesummary.Key, productname = salesummary.First().ProductName, totalqty = salesummary.Sum(s => s.Quantity) });
注意:该方案会将全量的销售明细数据加载到内存,大数据量场景下性能极差,不推荐使用。
内容的提问来源于stack exchange,提问作者fawad
相关产品推荐
相关产品推荐

