当使用非0的起始索引调用Skip()方法时,除了“现有的order-by”列之外,该方法还会自动附加其他列。这些附加的order-by列包含不在sort表达式中的其余列。 LINQ能够自动为我们处理这个问题,因为它为返回的数据提供了确定性排序;但是,当0传递给Skip()方法时(例如查询第一页时),似乎优化了方法并且不呈现上述附加的order-by列。这是有问题的,因为排序条件在Skip(0)和Skip(n)之间不一致。
另一位开发人员Dave也指出了同样的问题。 引用:“跳过(0)应生成跳过(n)所做的相同的行编号sql ...” 线程的链接:http://www.eggheadcafe.com/conversation.aspx?messageid=32045245&threadid=32045239
有没有人遇到过类似的问题?幸运的是,我们查询的数据有一个标识列,因此我们提出的解决方法是始终将标识列附加到现有排序表达式。我们很乐意听到其他创意方法或解决方案。
示例
下面的两个查询都从数据库中选择相同的列,并在列RequestReceivedDate上包含下降顺序。请注意,当存在具有相同RequestReceivedDate的记录时,Skip(10)生成的查询如何为剩余列附加额外排序,从而导致不同的数据排序。附加这些额外排序的想法很棒;但是,库应该为Skip(0)实现相同的逻辑,因此Skip(0)和Skip(n)将以相同的顺序返回数据。
[由Skip(0)生成的查询.Take(10)]
SELECT TOP (10) [t31].[PersonId], [t31].[value] AS [RequestReceivedDate2], ....
FROM (
SELECT [t0].[PersonId], (
SELECT MAX([t8].[RequestReceivedDate])
FROM [dbo].[EnrollRequest] AS [t8]
WHERE EXISTS(
SELECT NULL AS [EMPTY]
FROM [dbo].[DomainAccount] AS [t9]
WHERE ([t9].[DomainAccountId] = [t8].[DomainAccountId]) AND ([t9].[PersonId] = ([t0].[PersonId]))
)
) AS [value], ...
) AS [t31]
ORDER BY [t31].[value] DESC
[由Skip(10)生成的查询。获取(10)]
SELECT [t32].[PersonId], [t32].[value] AS [RequestReceivedDate2], ...
FROM (
SELECT ROW_NUMBER() OVER (ORDER BY [t31].[value] DESC) AS [ROW_NUMBER], [t31].[PersonId], [t31].[value], [t31].[FullAccountName], [t31].[LastName], ...
FROM (
SELECT [t0].[PersonId], (
SELECT MAX([t8].[RequestReceivedDate])
FROM [dbo].[EnrollRequest] AS [t8]
WHERE EXISTS(
SELECT NULL AS [EMPTY]
FROM [dbo].[DomainAccount] AS [t9]
WHERE ([t9].[DomainAccountId] = [t8].[DomainAccountId]) AND ([t9].[PersonId] = ([t0].[PersonId]))
)
) AS [value], ...
) AS [t32]
WHERE [t32].[ROW_NUMBER] BETWEEN @p21 + 1 AND @p21 + @p22
ORDER BY [t32].[ROW_NUMBER]
答案 0 :(得分:1)
显然,this issue is fixed in LINQ to SQL in .NET 4.0:
跳过(0)不再阻止急切加载
答案 1 :(得分:0)
从链接看起来这看起来像LINQ to SQL问题。并且在跳过后LINQ返回不同的结果时会产生无序的SELECT。
但是,除非指定order by子句,否则不能依赖SQL返回其行的顺序。
你能提供完整的样品吗?
答案 2 :(得分:0)
有关示例和解决方法,请参阅此文章 http://weblogs.asp.net/rajbk/archive/2009/09/30/linq-to-sql-paging-gotcha.aspx
简而言之,总是在分页之前对唯一的列执行排序,例如PK,以确保顺序一致。