.NET Core 5平台EF Core 5.0.8带LEFT JOIN与GroupBy的LINQ查询报错
问题原因
你遇到的报错是EF Core 3.0+的默认限制导致的:EF Core会尝试把整个LINQ查询翻译成SQL执行,一旦出现无法翻译为SQL的逻辑,就会抛出该异常,禁止隐式在客户端执行未翻译的逻辑。你当前写法有两处无法被EF Core 5.0翻译:
- 按完整
site实体作为分组键,SQL的GROUP BY子句不支持直接按整行/整个复合实体分组 - 直接返回
IGrouping类型的分组集合、对整个分组调用FirstOrDefault做判空的逻辑,也无法映射为SQL语法
解决方案
方案1:小数据量场景,直接开启客户端评估
如果查询返回的数据量不大,可以在分组逻辑前先把左连接的结果加载到内存,后续分组逻辑在内存执行即可,修改后的代码如下:
var a1 = (from site in db.Sites join machine in db.Machines on site.SiteId equals machine.SiteId into sm from siteMachines in sm.DefaultIfEmpty() where site.SiteId == SiteId // 新增该行,将前面的查询结果加载到内存后再执行后续分组 .AsEnumerable() group siteMachines by site into groupedSiteMachines select new { listedSite = groupedSiteMachines.Key, // 优化判空逻辑:只有分组内所有machine都为空时才返回null SiteMachines = groupedSiteMachines.All(x => x == null) ? null : groupedSiteMachines } ).ToList() ;
方案2:大数据量场景,改写为可被EF Core翻译的写法
如果查询数据量较大,不适合全量拉到内存处理,可以调整分组逻辑适配EF Core的翻译规则,不要用完整实体作为分组键,显式指定需要的字段即可:
var a1 = (from site in db.Sites join machine in db.Machines on site.SiteId equals machine.SiteId into sm from siteMachines in sm.DefaultIfEmpty() where site.SiteId == SiteId // 改用显式字段组成的匿名类作为分组键 group siteMachines by new { site.SiteId, site.SiteName /* 其他需要用到的site字段 */ } into groupedSiteMachines select new { listedSite = groupedSiteMachines.Key, // 显式返回筛选后的machine集合,不要直接返回整个IGrouping对象 SiteMachines = groupedSiteMachines.Where(x => x != null).ToList() } ).ToList() ;
内容的提问来源于stack exchange,提问作者K.Z
相关产品推荐
相关产品推荐

