Last 和 LastOrDefault 的 EF 行为

EF Behavior of Last and LastOrDefault

最近我在使用 EF 增强我的知识,为了保持最新,我只是在 Pluralsight 上寻找漏洞路径。考虑到这一点,我查看了朱莉·勒曼 (Julie Lerman) 的几门课程,顺便说一句,她是一位很棒的老师。

在课程中,对 linq 的一些内置功能以及它如何将其解释为查询进行了简短的回顾。我只是想知道这是否会通过功能发布进行更新,并想知道为什么会这样。

来自 Entity Framework 核心:入门课程引用:“最后的方法要求查询按方法排序,否则将 return 完整设置然后在内存中选择最后一个。”

谢谢

First/Last 方法都应该始终有一个 Order By 子句来尝试确保结果是可重复的。在 EF linq 表达式中使用 Last 方法确实没有充分的理由,只需颠倒顺序并使用 First 方法即可。唯一可能的原因是您需要查询表达式中的第一项和最后一项。

您可以通过 运行 探查器并检查生成的 SQL 了解很多关于 EF 正在做什么的信息。为什么 EF 需要一个 Order By 子句来执行最后一个操作,我想到了两个原因。第一个是 SQL 通常会使用类似 MAX(...) 表达式的东西来处理 LAST 类型场景,这需要一个或多个列来计算。第二个是它可能会考虑根据条件扭转现有秩序。我认为这将是第一个选项,但查看生成的 SQL 它实际上是第二个。

var test = context.Parents.OrderBy(x => x.Name).First();

SELECT TOP(1) [p].[ParentId], [p].[MasterParentId], [p].[Name]
FROM [Parents] AS [p]
ORDER BY [p].[Name] 
go

var test = context.Parents.OrderBy(x => x.Name).Last();

SELECT TOP(1) [p].[ParentId], [p].[MasterParentId], [p].[Name]
FROM [Parents] AS [p]
ORDER BY [p].[Name] DESC
go

您可能与 SQL 服务器一起使用的 MAX 方法可能依赖于提供程序,并且在使用多个 Order By 表达式时可能会出现问题。

值得注意的是,EF 支持 Linq 方法的能力是特定于提供程序实现的,因此并非所有提供程序或所有版本的 EF 都支持所有操作。例如,EF6 不支持 Last/LastOrDefault 方法,它们希望您反转 Order By 条件并使用 First*.

Last 方法需要 OrderBy 子句以避免在内存中执行操作的原因可能是 EF 会生成一个查询,该查询将值与 MAX(...) 操作进行比较。否则,它无法生成 SQL 语句来获取最后一行,并且必须加载所有内容以进行枚举。