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

时间:2019-09-10 14:24:54

标签: c# sql-server entity-framework linq entity-framework-core

在EntityFramework Core中得到此警告是什么问题?

我已经将MSSQL Datebase设置为区分大小写。

Latin1_General_100_CS_AS

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

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

2 个答案:

答案 0 :(得分:2)

EntityFramework无法将var selectedIndexPaths: Set<String> = [] override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: "testcell", for: indexPath) if selectedIndexPaths.contains(indexPath.description) { cell.accessoryType = .checkmark } else { cell.accessoryType = .none } override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { selectedIndexPaths.insert(indexPath.description) tableView.cellForRow(at: indexPath)?.accessoryType = .checkmark } override func tableView(_ tableView: UITableView, didDeselectRowAt indexPath: IndexPath) { selectedIndexPaths.remove(indexPath.description) tableView.cellForRow(at: indexPath)?.accessoryType = .none } 转换为SQL,因此它将所有的Student表加载到内存中,然后搜索满足相等性的第一个条目。

答案 1 :(得分:0)

您必须了解IEnumerableIqueryable之间的区别。

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

IQueryable对象似乎是IEnumerable,但是它并不表示可枚举的序列,而是表示将返回可枚举序列的查询。

IQueryable对象包含一个Expression和一个ProviderExpression是一般性描述,必须查询什么。 Provider知道谁将执行查询(通常是数据库管理系统),以及使用什么语言与该DBMS通信(通常是SQL)。

如果您开始枚举IQueryable,则可以显式使用GetEnumeratorMoveNext,或者通过调用foreach,ToList,Max,FirstOrDefault等隐式调用,这些将深入调用GetEnumerator和MoveNext,即表达式发送给提供程序,该提供程序将其转换为SQL并从DBMS中获取数据。提取的数据以IEnumerable的形式返回,其中调用了GetEnumerator和MoveNext。

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

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

实体框架只能将类和方法转换为它知道的SQL。实体框架不知道您自己的功能。实际上,实体框架不支持几种LINQ函数。参见Supported and Unsupported LINQ methods

String.Equals(string, StringComparison)是不受支持的方法之一。如果使用此函数,则编译器不会抱怨,您将在运行时看到此错误。它告诉您在调用函数之前首先要获取数据。 这可能会导致无效的行为。

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

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

由于不能使用Equals,因此警告信息指出在执行Where之前在本地获取数据。因此,可能有几个未通过Where的项目将从DBMS转移到您的本地进程。

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

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

这将导致类似于以下内容的SQL语句:

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

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