EF Core 6多表关联Group By查询报错,求兼容.NET6的解决方案
EF Core 6 分组查询翻译异常的解决方法
问题背景
原基于.NET Framework 4.7.1的Entity Framework查询代码如下:
var query = from c in context.Table1 join d in context.Table2 on c.enId equals d.enId join v in context.Table3 on d.sId equals v.sId group new {c, Name=d.Name, Email=d.Name, v=v.DocumentId} by new{c.enId, CDate=c.DialledDateTime} into grp orderby grp.Key.CDate select grp;
升级至.NET 6和EF Core 6后,出现以下翻译异常:
无法翻译查询。补充信息:不支持翻译包含未组合分组参数的'Select'操作。请将查询重写为可翻译的形式,或者通过插入'AsEnumerable'、'AsAsyncEnumerable'、'ToList'或'ToListAsync'调用显式切换到客户端评估。
原因分析
EF Core对分组查询的翻译逻辑与旧版Entity Framework(EF6)存在差异:EF6允许直接返回IGrouping类型的分组对象,但EF Core要求分组后的查询必须明确指定返回的结构(组合分组键与分组元素),否则无法将查询正确转换为SQL语句。
修改方案
方案一:重写查询为可翻译的结构(推荐,服务器端评估)
显式定义分组后要返回的内容,让EF Core能正确生成SQL:
var query = from c in context.Table1 join d in context.Table2 on c.enId equals d.enId join v in context.Table3 on d.sId equals v.sId group new {c, Name=d.Name, Email=d.Name, v=v.DocumentId} by new {c.enId, CDate=c.DialledDateTime} into grp orderby grp.Key.CDate select new { GroupKey = grp.Key, GroupItems = grp.ToList() };
该方案会在数据库端完成分组逻辑,性能最优,返回的结果包含分组键和对应元素列表,与原查询的业务逻辑一致。
方案二:切换到客户端评估(仅适用于小数据量场景)
若暂时不想调整查询结构,可通过AsEnumerable()将分组逻辑转移到客户端执行:
var query = from c in context.Table1 join d in context.Table2 on c.enId equals d.enId join v in context.Table3 on d.sId equals v.sId select new {c, Name=d.Name, Email=d.Name, v=v.DocumentId} into joinedData // 切换到客户端评估,后续分组逻辑在内存中执行 .AsEnumerable() group joinedData by new {joinedData.c.enId, CDate=joinedData.c.DialledDateTime} into grp orderby grp.Key.CDate select grp;
注意:此方案会先将所有连接后的数据加载到内存再分组,数据量大时会导致性能下降,需谨慎使用。
内容的提问来源于stack exchange,提问作者Sarvesh Patil
相关产品推荐
相关产品推荐

