使用`groupjoin`的查询无法翻译,尽管它被证明是受支持的
我不明白为什么这不翻译。这似乎正是这里描述的用例。
LINQ 表达式
DbSet<A>()
.GroupJoin(
inner: DbSet<B>(),
outerKeySelector: a => a.AId,
innerKeySelector: b => b.AId,
resultSelector: (a, bs) => new {
a = a,
bs = bs
})
DbSet<A>()
.GroupJoin(
inner: DbSet<B>(),
outerKeySelector: a => a.AId,
innerKeySelector: b => b.AId,
resultSelector: (a, bs) => new {
a = a,
bs = bs
})
产生错误:
无法翻译。以可翻译的形式重写查询,或通过插入对“AsEnumerable”、“AsAsyncEnumerable”、“ToList”或“ToListAsync”的调用,显式切换到客户端评估。有关详细信息,请参阅https://go.microsoft.com/fwlink/?linkid=2101038。
产生异常的 LINQ 代码是
编辑:也许我误解了文档,这是一个不翻译的例子。
执行类似于以下示例的查询会生成 Blog & IEnumerable 的结果。由于数据库(尤其是关系数据库)无法表示客户端对象的集合,因此 GroupJoin 在许多情况下不会转换为服务器。它要求您从服务器获取所有数据以在没有特殊选择器的情况下执行 GroupJoin(下面的第一个查询)。但是,如果选择器限制选择的数据,那么从服务器获取所有数据可能会导致性能问题(下面的第二个查询)。这就是 EF Core 不翻译 GroupJoin 的原因。
但后来我的问题变成了:如何在不需要导航属性的情况下实现我正在寻找的结果?
回答
链接文档中的解释只是遵循 EF Core 团队的愿景并且很荒谬,因为它当然可以轻松翻译 - 我在这里与团队进行了长时间的讨论Query with GroupBy 或 GroupJoin throws exception #17068并在此处继续Query: Support GroupJoin 当它是最终查询运算符 #19930 时,试图说服他们为什么应该支持它,无论参数如何都没有运气。
重点是(这就是当前的解决方法)它可以像相关子查询 ( SelectMany)一样被处理,它被正确地翻译和处理(即使查询结果形状没有 SQL 等效项。
无论如何,当前状态是“需要设计”(无论这意味着什么),解决方法是将连接替换为相关子查询(这是 EF Core 在查询转换期间“扩展”集合导航属性时在内部使用的)。
在你的情况下,更换
join b in ctx.Bs on a.aId equals b.aId into bs
和
let bs = ctx.Bs.Where(b => a.aId == b.aId)
但是,我强烈建议添加和使用导航属性。不知道为什么你“不能使用”它们,在不投影实体的 LINQ to Entities 中,它们只为关系提供元数据,从而自动生成必要的连接。通过不定义它们,您只会给自己带来不必要的限制(除了 EF Core 限制/错误之外)。一般来说,EF Core 在使用导航属性而不是手动连接时效果更好并支持更多功能。