Entity Framework无法转换LINQ表达式 技术求助
需求与问题
我有如下数据模型,需要按以下条件对ResponseItem列表进行分组:
- 第一步:按
ResponseItem.Group分组 - 第二步:按
ResponseItem.SubGroup分组,但仅保留每个SubGroup中CreationDate最新的条目
数据模型定义
public class ResponseItem { public string Group { get; set; } public string SubGroup { get; set; } public double Value { get; set; } public DateTime CreationDate { get; set; } } public class GroupedResponseItem { public string Group { get; set; } public List<ResponseItem> Items { get; set; } }
报错的实现代码
尝试了以下实现,但运行时出现错误:
public List<GroupedResponseItem> GetGroupedData( IQueryable<ResponseItem> responseItems ) { return responseItems .OrderByDescending(i => i.CreationDate) .GroupBy(i => i.Group) .Select(grp => new GroupedResponseItem() { Group = grp.Key, Items = grp .GroupBy(i => new { i.SubGroup }) .Select(grp => grp.First()) .Select(i => new ResponseItem() { SubGroup = i.SubGroup, CreationDate = i.CreationDate, Value = i.Value }).ToList() }) .ToList(); }
运行报错信息
'The LINQ expression 'ProjectionBindingExpression: 0' could not be translated. Either rewrite the query in a form that can be translated, or switch to client evaluation explicitly by inserting a call to 'AsEnumerable', 'AsAsyncEnumerable', 'ToList', or 'ToListAsync'
我使用的是.NET 6版本的Entity Framework。另外,如果不进行第二次分组,查询可以正常运行:
正常运行的简化代码(无二次分组)
public List<GroupedResponseItem> GetGroupedData(IQueryable<ResponseItem> responseItems) { return responseItems .OrderByDescending(i => i.CreationDate) .GroupBy(i => i.Group) .Select(grp => new GroupedResponseItem() { Group = grp.Key, Items = grp .Select(i => new ResponseItem() { SubGroup = i.SubGroup, CreationDate = i.CreationDate, Value = i.Value }) .ToList() }) .ToList(); }
解决方案
EF Core 6对嵌套GroupBy的LINQ表达式翻译支持有限,导致出现上述错误。可以通过以下两种方式解决:
方式1:先筛选每个SubGroup的最新记录,再分组
先在数据库层面找出每个(Group, SubGroup)组合下CreationDate最新的条目,再按Group分组,避免嵌套分组操作:
public List<GroupedResponseItem> GetGroupedData(IQueryable<ResponseItem> responseItems) { // 获取每个SubGroup的最新记录 var latestSubGroupItems = responseItems .GroupBy(i => new { i.Group, i.SubGroup }) .Select(g => g.OrderByDescending(i => i.CreationDate).First()) .AsQueryable(); // 按Group分组组装结果 return latestSubGroupItems .GroupBy(i => i.Group) .Select(grp => new GroupedResponseItem { Group = grp.Key, Items = grp.Select(i => new ResponseItem { SubGroup = i.SubGroup, CreationDate = i.CreationDate, Value = i.Value }).ToList() }) .ToList(); }
方式2:客户端评估(适合小数据量场景)
如果数据量不大,可以先将数据加载到内存中,再执行嵌套分组操作,绕开EF Core的翻译限制:
public List<GroupedResponseItem> GetGroupedData(IQueryable<ResponseItem> responseItems) { // 先将数据加载到内存 var items = responseItems.OrderByDescending(i => i.CreationDate).ToList(); return items .GroupBy(i => i.Group) .Select(grp => new GroupedResponseItem { Group = grp.Key, Items = grp .GroupBy(i => i.SubGroup) .Select(subGrp => subGrp.First()) .Select(i => new ResponseItem { SubGroup = i.SubGroup, CreationDate = i.CreationDate, Value = i.Value }).ToList() }) .ToList(); }
内容的提问来源于stack exchange,提问作者user2382627
相关产品推荐
相关产品推荐

