简体   繁体   English

无法翻译 LINQ 表达式,将在本地计算

[英]The LINQ expression could not be translated and will be evaluated locally

Im getting this WARNING in EntityFramework Core what is wrong?我在 EntityFramework Core 中收到此警告有什么问题?

I already set MSSQL Datebase to Case Sensitive.我已经将 MSSQL 数据库设置为区分大小写。

Latin1_General_100_CS_AS Latin1_General_100_CS_AS

var test = await _context.Students
                .FirstOrDefaultAsync(m => m.LastName.Equals("ALEXANDER", StringComparison.InvariantCultureIgnoreCase));

Microsoft.EntityFrameworkCore.Query:Warning: The LINQ expression 'where [m].LastName.Equals("ALEXANDER", InvariantCultureIgnoreCase)' could not be translated and will be evaluated locally. Microsoft.EntityFrameworkCore.Query:Warning:无法翻译 LINQ 表达式 'where [m].LastName.Equals("ALEXANDER", InvariantCultureIgnoreCase)',将在本地进行评估。

You have to be aware of the difference between IEnumerable and Iqueryable .您必须了解IEnumerableIqueryable之间的区别。

An IEnumerable object represents a sequence of objects.一个IEnumerable对象表示一个对象序列。 It holds everything to enumerate over this sequence: you can ask for the first element of the sequence, and once you've got an element you can ask for the next one, as long as there is a next one.它包含所有要枚举的序列:你可以请求序列的第一个元素,一旦你有了一个元素,你就可以请求下一个元素,只要有下一个元素。

An IQueryable object seems like an IEnumerable, however, it does not represent an enumerable sequence, it represents the potential to get an IEnumerable sequence.一个IQueryable对象看起来像一个 IEnumerable,但是,它并不代表一个可枚举的序列,它代表了获得一个 IEnumerable 序列的潜力。

The IQueryable object holds an Expression and a Provider . IQueryable 对象包含一个Expression和一个Provider The Expression is a generic description expressing what must be queried. Expression是一个通用描述,表示必须查询的内容。 The Provider knows who will execute the query (usually a database management system) and what language is used to communicate with this DBMS (usually SQL). Provider知道谁将执行查询(通常是数据库管理系统)以及使用什么语言与此 DBMS 通信(通常是 SQL)。

If you start enumerating an IQueryable, either explicitly using GetEnumerator and MoveNext , or implicitly by calling foreach, ToList, Max, FirstOrDefault, etc, which will deep inside call GetEnumerator and MoveNext, the Expression is sent to the Provider, who will translate it into SQL and fetch the data from the DBMS.如果您开始枚举 IQueryable,或者显式使用GetEnumeratorMoveNext ,或者通过调用 foreach、ToList、Max、FirstOrDefault 等隐式调用,这将在内部调用 GetEnumerator 和 MoveNext,则表达式将发送到提供者,提供者会将其翻译成SQL 并从 DBMS 获取数据。 The fetched data is returned as an IEnumerable, of which the GetEnumerator and MoveNext are called.获取的数据以 IEnumerable 的形式返回,其中调用 GetEnumerator 和 MoveNext。

So the query is not executed before you call GetEnumerator and MoveNext.因此,在调用 GetEnumerator 和 MoveNext 之前不会执行查询。

What does this have to do with my question?这和我的问题有什么关系?

Entity framework can only convert classes and methods to SQL that it knows about.实体框架只能将类和方法转换为它知道的 SQL。 Entity Framework does not know your own functions.实体框架不知道您自己的功能。 In fact, there are several LINQ function that are not supported by entity framework.事实上,有几个 LINQ 功能是实体框架不支持的。 See Supported and Unsupported LINQ methods请参阅支持和不支持的 LINQ 方法

One of the unsupported methods is String.Equals(string, StringComparison) .不支持的方法之一是String.Equals(string, StringComparison) If you use this function, the compiler can't complain, because the compiler does not know what functions are supported by your version of entity framework.如果你使用这个函数,编译器不会抱怨,因为编译器不知道你的实体框架版本支持哪些函数。 Therefore you won't see this error at compile time, you'll see it at runtime.因此,您在编译时不会看到此错误,您会在运行时看到它。

The error tells you that the data will first be fetched before the function is called.该错误告诉您在调用函数之前将首先获取数据。 This might lead to inefficient behaviour.这可能会导致低效行为。

Your LINQ statement is equal to (leave out the async-await, not part of the problem)您的 LINQ 语句等于(省略异步等待,不是问题的一部分)

var test = dbContext.Students
    .Where(student => student.LastName.Equals("ALEXANDER", StringComparison.InvariantCultureIgnoreCase))
    .FirstOrDefault();
    

Since Equals can't be used, the warning says that the data is fetched locally before the Where is executed.由于无法使用 Equals,因此警告说数据是在执行 Where 之前在本地获取的。 So it might be that several items that will not pass the Where will be transferred from the DBMS to your local process.因此,可能有几个不会通过 Where 的项目将从 DBMS 转移到您的本地进程。

If your database can ignore case sensitivity, consider changing your code to:如果您的数据库可以忽略大小写敏感,请考虑将代码更改为:

var test = dbContext.Students
    .Where(student => student.LastName == "ALEXANDER")
    .FirstOrDefault();

This will result in a SQL statement similar to:这将产生类似于以下内容的 SQL 语句:

SELECT TOP 1 * from myDatabase.Students where LastName = "ALEXANDER"

(not sure if this is correct SQL, since I use entity framework my SQL is a bit rusty. I guess you'll get the gist) (不确定这是否是正确的 SQL,因为我使用实体框架,所以我的 SQL 有点生疏。我想你会明白的)

EntityFramework 无法将Equals("ALEXANDER", StringComparison.InvariantCultureIgnoreCase)转换为 SQL,因此它会将所有 Student 表加载到内存中,然后搜索满足等式的第一个条目。

I got this error by querying my LINQ methods in the wrong order before calling a ToListAsync call at the end.在最后调用 ToListAsync 调用之前以错误的顺序查询我的 LINQ 方法,我得到了这个错误。

Here was the code that threw this error for me:这是为我引发此错误的代码:

var sideeffects = await Context.SideEffects.Include(x => x.Language)
.Select(x => new SideEffect() { Name = x.Name, Language = x.Language, CleanName = x.CleanName, Id = x.Id, SideEffects = x.SideEffects, Related = x.Related, DrugSideEffects = x.DrugSideEffects })
.Where(x => !x.IsDeleted).ToListAsync();

Calling the where at the end after the select and include screwed up the query and created this error.在 select 和 include 之后调用 where 会搞砸查询并创建此错误。 When I moved the where clause to the beginning, it cleared the error and allowed the query to be performed successfully with all required fields:当我将 where 子句移到开头时,它清除了错误并允许使用所有必填字段成功执行查询:

var sideeffects = await Context.SideEffects.Where(x => !x.IsDeleted)
.Include(x => x.Language)
.Select(x => new SideEffect() { Name = x.Name, Language = x.Language, CleanName = x.CleanName, Id = x.Id, SideEffects = x.SideEffects, Related = x.Related, DrugSideEffects = x.DrugSideEffects }).ToListAsync();

Be mindful of the order of your LINQ queries when using entity framework - especially when using a Select or an Include.使用实体框架时要注意 LINQ 查询的顺序——尤其是在使用 Select 或 Include 时。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM