从 EF Core 2 迁移到 EF Core 3

沙里亚尔

将我的项目从 (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.
用户6311045

您的问题的答案将非常冗长,因为它对应于 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())。

总而言之,您可以阅读一些有趣的帖子:

ef core 3 中的 40 个重大变化

公布实体框架核心 3.0 预览版 9 和实体框架 6.3 预览版 9

github上的EF核心问题

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章