LINQ 表达式无法翻译,将在本地进行评估

Aor*_*337 16 c# linq sql-server entity-framework entity-framework-core

我在 EntityFramework Core 中收到此警告,有什么问题?

我已经将 MSSQL 数据库设置为区分大小写。

Latin1_General_100_CS_AS

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

Microsoft.EntityFrameworkCore.Query:警告:LINQ 表达式 'where [m].LastName.Equals("ALEXANDER", InvariantCultureIgnoreCase)' 无法翻译,将在本地进行评估。

Har*_*lse 34

你必须要知道之间的差异IEnumerableIqueryable

一个IEnumerable对象代表一个对象序列。它包含要枚举这个序列的所有内容:您可以请求序列的第一个元素,一旦获得了一个元素,您就可以请求下一个元素,只要有下一个元素即可。

一个IQueryable对象看起来像一个 IEnumerable,然而,它并不代表一个可枚举的序列,它代表了获得一个 IEnumerable 序列的可能性。

IQueryable 对象包含 anExpression和 a Provider。这Expression是一个通用描述,表示必须查询的内容。该Provider知道谁将会执行查询(通常是一个数据库管理系统)和语言则使用该数据库管理系统(通常是SQL)沟通一下。

如果您开始枚举 IQueryable,或者显式使用GetEnumeratorand MoveNext,或者通过调用 foreach、ToList、Max、FirstOrDefault 等隐式调用 GetEnumerator 和 MoveNext 等,则表达式将发送到提供程序,提供程序将其转换为 SQL 和从 DBMS 中获取数据。获取的数据作为 IEnumerable 返回,其中调用 GetEnumerator 和 MoveNext。

因此,在调用 GetEnumerator 和 MoveNext 之前不会执行查询。

这和我的问题有什么关系?

实体框架只能将类和方法转换为它知道的 SQL。实体框架不知道您自己的功能。事实上,有几个 LINQ 函数是实体框架不支持的。请参阅支持和不支持的 LINQ 方法

不受支持的方法之一是String.Equals(string, StringComparison). 如果你使用这个函数,编译器不会抱怨,因为编译器不知道你的实体框架版本支持哪些函数。因此你不会在编译时看到这个错误,你会在运行时看到它。

该错误告诉您将在调用函数之前首先获取数据。这可能会导致低效的行为。

您的 LINQ 语句等于(省略异步等待,不是问题的一部分)

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

由于不能使用 Equals,警告说在执行 Where 之前在本地获取数据。因此,可能不会通过 Where 的几个项目将从 DBMS 传输到您的本地进程。

如果您的数据库可以忽略区分大小写,请考虑将您的代码更改为:

var test = dbContext.Students
    .Where(student => student.LastName == "ALEXANDER")
    .FirstOrDefault();
Run Code Online (Sandbox Code Playgroud)

这将产生类似于以下内容的 SQL 语句:

SELECT TOP 1 * from myDatabase.Students where LastName = "ALEXANDER"
Run Code Online (Sandbox Code Playgroud)

(不确定这是否是正确的 SQL,因为我使用实体框架我的 SQL 有点生疏。我想你会明白要点)


Eli*_*s N 2

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

  • 您只是重新表述了异常消息,这不是解决方案。 (23认同)
  • 是的,但是 op 确认东西正在加载到内存中。 (3认同)