将我的项目从 (dotnet core 2/ef core 2) 升级到 (dotnet core 3/ef core 3) 后,几乎所有的实体框架 LINQ 查询都被破坏了。虽然我已经阅读了这篇文章,但仍然不清楚该怎么做。
以下是我遇到问题的一些示例:
var league = await dbContext.League.LastAsync();
虽然这段代码在 ef core 2 中运行良好,但在 ef core 3 中抛出异常。我能找到的唯一解决方法是以下代码,它仍然不是我想要的,因为它不像以前那样异步。
var league = dbContext.League.AsEnumerable().Last();
抛出相同异常的另一个示例是以下代码:
var user = await dbContext.User.FirstOrDefaultAsync(u =>
u.UserId == userId && string.Equals(u.Token, token, StringComparison.InvariantCulture));
我仍然可以使用 AsEnumerable() 但 FirstOrDefault 的异步版本在那里不可用,所以这不是一个选项。有人可以指导我吗?
编辑
这是例外:
System.InvalidOperationException: The LINQ expression 'Last<League>(DbSet<League>)' could not be translated. Either rewrite the query in a form that can be translated, or switch to client evaluation explicitly by inserting a call to either AsEnumerable(), AsAsyncEnumerable(), ToList(), or ToListAsync(). See https://go.microsoft.com/fwlink/?linkid=2101038 for more information.
您的问题的答案将非常冗长,因为它对应于 EF Core 3.0 中发生的一些不同更改;所以,让我们只考虑其中的一小部分。
正如你在你的问题中提到的,微软在这篇文章中对 3.0 版的变化有一些令人困惑的描述。
上面帖子的第一部分是:“不再在客户端上评估 LINQ 查询”。它说,在开发人员过去常常编写包含两个部分的查询之前;一部分是对数据库的查询,另一部分是只有客户端代码才知道的表达式。在这种情况下client evaluation of potentially expensive expressions only triggered a warning
。但是在新版本中,EF core 只允许在客户端计算最后一次 Select() 调用,并且当存在无法转换为 SQL 或参数的表达式时抛出异常。
为了澄清这一部分,让我们看一下 Diego Vega 在他的EF Core 3.0 公告博客文章中描述的示例。
显式切换到客户端评估:如果您的查询基于无法转换为 SQL 的表达式过滤数据,您可能需要通过插入对 AsEnumerable()、AsAsyncEnumerable()、ToList() 或ToListAsync() 在查询中间。例如,以下查询将不再适用于 EF Core 3.0,因为 where 子句中的谓词之一需要客户端评估:
var specialCustomers = context.Customers
.Where(c => c.Name.StartsWith(n) && IsSpecialCustomer(c));
但是如果您知道在客户端处理部分过滤器是合理的,您可以将查询重写为:
var specialCustomers = context.Customers
.Where(c => c.Name.StartsWith(n))
.AsEnumerable() // Start using LINQ to Objects (switch to client evaluation)
.Where(c => IsSpecialCustomer(c));
在上面的例子中IsSpecialCustomer(c)
是一个不能转换为 SQL 的方法,因为它是一个 C# 方法,它只能在客户端代码中使用。所以开发者要么以可翻译的形式重写查询,要么查询数据库,然后将数据库结果评估给客户端使用.AsEnumerable()
,然后可以根据IsSpecialCustomer(c)
返回值过滤结果。这就是为什么您仍然可以AsEnumerable()
在代码中访问的原因。
现在,让我们看看为什么FirstOrDefaultAsync()
方法不可用?
那么,造成这种情况的原因有两个。
我之前回答过第一个原因:检测不可组合 SQL 的代码已在 3.0 版中删除。
第二个是:查询管道不理解表达式树中的异步可查询运算符(例如:当您尝试访问它时EF.CompileQuery()
)。
总而言之,您可以阅读一些有趣的帖子:
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句