尽管细节可能有所不同,但所接受的答案在描述发出的查询有何不同方面基本上是正确的。我经常看到实体框架发出的查询为“TOP (@maxPageSize) .... WHERE [ROW_NUMBER] > @skip”,这可能是相同的差异,但我不能 100% 确定它是否生成相同的查询执行计划。
需要明确注意的重要区别是,当“ORDER BY”不包含唯一的列名时,这可能会产生不同的结果。
在我编写的代码中,当 @skip 值为 0 时,我们省略了“Skip”。我们有一个条目显示为最终条目。如果您随后转到应用了 @skip 值的下一页,则相同的条目将显示为该页面上的第一项。应该位于至少其中一个位置的“捆绑”项目从未出现。以下是每个发出的 SQL:
不跳过(在第 1 页生成):
SELECT TOP ({take number}) [Extent1].[Table1ID] AS [Table1ID], {snip a lot of other columns}
FROM [dbo].[Table1] AS [Extent1]
LEFT OUTER JOIN [dbo].[Table2] AS [Extent2] ON [Extent1].[Table2ID] = [Extent2].[Table2ID]
WHERE ({my where clause conditions})
ORDER BY [Extent2].[MySortColumn] ASC
Skip:
SELECT TOP ({take number}) [Filter1].[Table1ID], {snip a lot of other columns}
FROM ( SELECT [Extent1].[Table1ID] AS [Table1ID], {snip a lot of other columns}, row_number() OVER (ORDER BY [Extent2].[MySortColumn] ASC) AS [row_number]
FROM [dbo].[Table1] AS [Extent1]
LEFT OUTER JOIN [dbo].[Table2] AS [Extent2] ON [Extent1].[Table2ID] = [Extent2].[Table2ID]
WHERE ({my where clause conditions})
) AS [Filter1]
WHERE [Filter1].[row_number] > {skip number}
ORDER BY [Filter1].[MySortColumn] ASC
重要的一点是回到“SQL 101”并记住这一点如果没有“order by”,则无法保证订单 https://sqlblogcasts.com/blogs/sqlandthelike/archive/2010/06/27/sql-101-without-order-by-order-is-not-guaranteed.aspx。这种发出的差异会导致一个项目在网格的多个页面上重复,而另一个项目根本不会显示,这让我发现这在实体框架中更为重要,其中生成的确切 SQL 并不直接由您控制,并且未来的 EF 版本可能会出现意外的变化.
目前,您可以通过始终包含 Skip(0) 来避免这种情况,它将发出第二个查询,但 {skip number} 只是为零。在我的测试中,这似乎总是使用 T-SQL 的默认规则为决胜局发出相同的顺序。我认为假设这一定会在实体框架的未来版本中起作用并不是最佳实践。相反,我建议您考虑探索打破平局的策略 http://www.itprotoday.com/software-development/t-sql-tiebreakers你自己。就我而言,应该可以打破“Table1ID”的束缚,因为它代表唯一的身份主键列。不过,所附文章针对更复杂的情况提供了建议。