在将我的项目从(dotnet 2/ef 2)升级到(dotnet 3/ef 3)之后,我的实体框架LINQ查询几乎全部中断。虽然我已经读过这,但还不清楚该怎么做。
下面是一些我有问题的例子:
var league = await dbContext.League.LastAsync();虽然这段代码在ef核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.发布于 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:
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()方法不可用?
造成这种情况的原因有两个。
我已经回答了第一个原因:在3.0版中删除了检测不可组合SQL的代码。
第二个问题是:查询管道不理解表达式树中的异步可查询操作符(例如:当您试图在EF.CompileQuery()).上访问它时)。
总之,有几篇有趣的文章可以读到:
发布于 2019-09-30 21:15:07
OrderByDesc(),然后使用FirstAsync()。(https://github.com/aspnet/EntityFrameworkCore/issues/18211)在没有任何过滤器的情况下在AsEnumerable()上调用DbSet将在本地删除所有数据,而不是在生产中执行。尝试重写上面的内容,并监视生成的SQL,以确保获得了性能良好的查询。
https://stackoverflow.com/questions/58166970
复制相似问题