首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >从EF Core 2迁移到EF Core 3

从EF Core 2迁移到EF Core 3
EN

Stack Overflow用户
提问于 2019-09-30 11:26:02
回答 2查看 8.4K关注 0票数 12

在将我的项目从(dotnet 2/ef 2)升级到(dotnet 3/ef 3)之后,我的实体框架LINQ查询几乎全部中断。虽然我已经读过,但还不清楚该怎么做。

下面是一些我有问题的例子:

代码语言:javascript
复制
var league = await dbContext.League.LastAsync();

虽然这段代码在ef核2中运行得很好,但它会在ef core 3中抛出异常。我能找到的唯一解决办法是下面的代码,但它仍然不是我想要的,因为它不像以前那样异步。

代码语言:javascript
复制
var league = dbContext.League.AsEnumerable().Last();

引发相同异常的另一个示例是以下代码:

代码语言:javascript
复制
var user = await dbContext.User.FirstOrDefaultAsync(u =>
                u.UserId == userId && string.Equals(u.Token, token, StringComparison.InvariantCulture));

我仍然可以使用AsEnumerable(),但是异步版本的FirstOrDefault是不可用的,所以这不是一个选项。有人能用这个指引我吗?

编辑

这是一个例外:

代码语言:javascript
复制
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.
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2019-10-01 02:02:08

对您的问题的回答将非常冗长,因为它对应于EFCore3.0中发生的一些不同的更改;因此,让我们考虑一下它的一部分。

正如您在问题中提到的,对于这个职位中3.0版本的更改,微软有一种令人困惑的描述。

上面文章的第一部分是:'LINQ查询不再在客户端上进行评估‘。它说,在开发人员过去编写包含两个部分的查询之前,其中一部分是数据库上的查询,另一部分是只知道客户端代码的表达式。在这种情况下,client evaluation of potentially expensive expressions only triggered a warning。但是在新版本中,EF核心只允许在客户端上计算最后一个Select()调用,并在有不能转换为SQL或参数的表达式时抛出异常。

为了澄清这一部分,让我们看一看迭戈·维加在他的EF核心3.0公告博客文章中描述的一个例子。

切换到客户机计算显式:如果查询基于不能转换为的表达式筛选数据,则可能需要显式切换到客户端计算,方法是在查询中间插入对AsEnumerable()、AsAsyncEnumerable()、ToList()或ToListAsync()的调用。例如,由于where子句中的一个谓词需要客户端计算,下面的查询将不再适用于EF Core 3.0:

代码语言:javascript
复制
var specialCustomers = context.Customers
    .Where(c => c.Name.StartsWith(n) && IsSpecialCustomer(c));

但是,如果您知道在客户端上处理部分筛选器是合理的,则可以将查询重写为:

代码语言:javascript
复制
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()方法不可用?

造成这种情况的原因有两个。

我已经回答了第一个原因:在3.0版中删除了检测不可组合SQL的代码。

第二个问题是:查询管道不理解表达式树中的异步可查询操作符(例如:当您试图在EF.CompileQuery()).上访问它时)。

总之,有几篇有趣的文章可以读到:

40破坏ef核心的坏变化3

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

EF关于github的核心问题

票数 12
EN

Stack Overflow用户

发布于 2019-09-30 21:15:07

  1. 对某些属性使用OrderByDesc(),然后使用FirstAsync()。(https://github.com/aspnet/EntityFrameworkCore/issues/18211)
  2. 不变量比较没有翻译,可能是客户端以前评估过的。根据数据库排序规则设置的不同,您可能只需在这里做一个普通的等号。

在没有任何过滤器的情况下在AsEnumerable()上调用DbSet将在本地删除所有数据,而不是在生产中执行。尝试重写上面的内容,并监视生成的SQL,以确保获得了性能良好的查询。

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/58166970

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档