当最上面的投影包含方法调用时,EF Core 客户端评估不起作用

Posted

技术标签:

【中文标题】当最上面的投影包含方法调用时,EF Core 客户端评估不起作用【英文标题】:EF Core client evaluation doesn't work, when top most projection contains method call 【发布时间】:2020-10-08 23:05:26 【问题描述】:

documentation 表示在最后一次调用Select 时有一些不能被翻译成 SQL 的代码是可以的:

在 EF Core 3.0 中,我们将客户端评估限制为仅在***投影上进行(本质上是对 Select() 的最后一次调用)。当 EF Core 3.0 检测到无法在查询中的其他任何位置翻译的表达式时,它会引发运行时异常。

虽然我在最后一次调用 Select() 时使用了一个方法调用,但我收到了一个 System.InvalidOperationException 异常抱怨:

无法翻译 LINQ 表达式...。以可翻译的形式重写查询,或通过插入对 AsEnumerable()、AsAsyncEnumerable()、ToList() 或 ToListAsync() 的调用显式切换到客户端评估。请参阅https://go.microsoft.com/fwlink/?linkid=2101038 了解更多信息。

如果我这样写,我可以让我的代码工作:

// this query works find and gets evaluated well
from entity in DbContext.DbSet<MyEntity>
where <... some conditions ... >
select new EntityDto() 

    Prop1 = entity.X.Y,
    Prop2 = someMethod(entity.Z.T),
    Prop3 = <some value>,
    ...
    Prop4 = <some value>,

上述 LINQ 查询中的 select 子句是一个长代码,因此我决定将其移至另一个单独的私有方法,以便获得更易读的代码。由于文档中的内容,我希望这可以工作:

// this is the code that gets exception at runtime:
from entity in DbContext.DbSet<MyEntity>
where <... some conditions ... >
select CreateDto(entity.X, entity.Z)

上面的代码 sn-p 得到了我告诉的异常。我该如何解决这个问题?为什么英孚抱怨客户评价?

【问题讨论】:

【参考方案1】:

虽然我在最后一次调用 Select() 时使用了方法调用,但

抱歉,“禁用”是“禁用”,而不是“禁用,除非您在上次调用 Select 时使用它”。

不要调用该方法。将您获得的内容包装到 AsEnumerable,然后(在枚举中)项目并调用该方法。完成。

【讨论】:

但是文档是这样说的:“除非你在最后一次调用 Select 时使用它”,而不是我! 嗯,错误信息很清楚。他们做了一个改变。我刚刚在文档中阅读了 t 并且文档显然是错误的。不,这让我感到奇怪 - 即使在 v3 中,ef core 也是一团糟。

以上是关于当最上面的投影包含方法调用时,EF Core 客户端评估不起作用的主要内容,如果未能解决你的问题,请参考以下文章

EF Core 迁移

EF:“包含”导航属性,当使用“选择”投影创建包装对象时

Linq 投影:获取新投影实体的参考

EF Core 上下文不包含添加实体的更改

使用 EF Core 过滤包含时的列名无效

如何在 EF Core 的 Hot Chocolate 中打开和关闭包含