LINQ Skip(0)vs Skip(n),返回不一致的排序表达式

时间:2009-07-06 22:12:48

标签: linq

当使用非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]

3 个答案:

答案 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,以确保顺序一致。