EF Core嵌套GroupJoin的LINQ表达式无法翻译为SQL如何解决
嵌套GroupJoin翻译失败问题解决方案
问题根因
两层嵌套GroupJoin的写法本身语法没有问题,但EF Core查询翻译器不支持对多个独立构造的IQueryable做嵌套GroupJoin的服务端翻译,这类写法会被判定为无法转换为等价SQL,最终触发客户端评估报错。
EF Core对层级嵌套集合投影的翻译,依赖实体间配置好的外键导航属性识别表关联关系,手动拆分三个独立查询再嵌套关联的写法,翻译器无法识别其与导航属性层级的等价性,因此无法生成对应SQL。
可直接落地的无客户端评估实现方案
直接通过实体配置好的导航属性做层级投影即可,EF Core 5.0+版本可以自动将该写法翻译为服务端执行的SQL,全程不会触发客户端评估,执行效率远高于内存拼接:
return await Db.WorkListCategories .Where(c => c.CompanyId == null || c.CompanyId.Value == companyId) .Select(c => new WorkListCategoryFull<WorkListSubCategoryFull> { Id = c.Id, Name = c.Name, IsEditable = c.IsEditable, SubCategories = c.SubCategories .Where(sc => sc.Category.CompanyId == null || sc.Category.CompanyId.Value == companyId) .Select(sc => new WorkListSubCategoryFull { Id = sc.Id, Name = sc.Name, WorkLists = sc.WorkLists .Where(wl => wl.SubCategory.Category.CompanyId == null || wl.SubCategory.Category.CompanyId.Value == companyId) .Select(wl => new WorkList { Id = wl.Id, Name = wl.Name }) .ToList() }) .ToList() }) .ToListAsync(cancellationToken);
前置要求
需要先在实体类中配置与数据库结构匹配的导航属性:
WorkListCategory实体中定义类型为ICollection<WorkListSubCategory>的SubCategories导航属性,外键对应WorkListSubCategory.CategoryIdWorkListSubCategory实体中定义类型为ICollection<WorkList>的WorkLists导航属性,外键对应WorkList.SubCategoryId
该写法生成的SQL会自动完成三表关联查询,EF Core会在查询结果组装阶段自动映射为需要的三级嵌套结构,所有过滤逻辑都在数据库侧完成,不会出现全表拉取到内存再过滤的性能问题。
内容的提问来源于stack exchange,提问作者Thodor20
相关产品推荐
相关产品推荐

