繁体   English   中英

使用.Skip(0)时,强制LINQ to SQL使用RowNumber()而不是Top n

[英]Force LINQ to SQL to use RowNumber() instead of Top n When Using .Skip(0)

有没有一种方法可以使LINQ to SQL在使用Skip(0)时避免使用TOP X? 我有一个查询,对于每个分页结果都可以正常运行……除了第1页。我已经对该查询进行了概要分析,并且引入TOP子句只会杀死它。 我对为什么会这样感到困惑,但事实确实如此。 但是,在1到10之间使用RowNumber可以正常工作。

有没有一种方法可以使LINQ to SQL在使用Skip(0)时避免使用TOP X? 我有一个查询,对于每个分页结果都可以正常运行……除了第1页。我已经对该查询进行了概要分析,并且引入TOP子句只会杀死它。 我对为什么会这样感到困惑,但事实确实如此。 但是,在1到10之间使用RowNumber可以正常工作。

罪魁祸首似乎是我的WHERE子句中的EXISTS条件。 产生的SQL在下面。 在SQL Manager中,此查询运行良好,并返回14个结果...但是,一旦我添加了TOP 10,它就会超时(如LINQ那样)。 但是,如果我在where子句中注释EXISTS,那么问题就消失了。

SELECT 
    t0.ProtectiveOrderID, 
    t3.DocketID, 
    t3.DocketNumber AS CaseNumber, 
    t3.PartySuffix AS CaseNumberSuffix, 
    t5.FirstName AS RespondentNameFirst, 
    t5.MiddleName AS RespondentNameMiddle, 
    t5.LastName AS RespondentNameLast, 
    t5.NameSuffix AS RespondentNameSuffix,
    t4.FirstName AS ProtectedNameFirst, 
    t4.MiddleName AS ProtectedNameMiddle, 
    t4.LastName AS ProtectedNameLast, 
    t4.NameSuffix AS ProtectedNameSuffix, 
    t3.ChildNextFriendFirstName AS ChildNextFriendNameFirst, 
    t3.ChildNextFriendMiddleName AS ChildNextFriendNameMiddle, 
    t3.ChildNextFriendLastName AS ChildNextFriendNameLast, 
    t3.ChildNextFriendNameSuffix
FROM dbo.ProtectiveOrder AS t0
INNER JOIN (
SELECT MAX(t1.ProtectiveOrderID) AS value
FROM dbo.ProtectiveOrder AS t1
GROUP BY t1.DocketID
) AS t2 ON t0.ProtectiveOrderID = t2.value
LEFT OUTER JOIN dbo.Docket AS t3 ON t3.DocketID = t0.DocketID
LEFT OUTER JOIN dbo.Directory AS t4 ON t4.DirectoryID = t3.ProtectedPartyID
LEFT OUTER JOIN dbo.Directory AS t5 ON t5.DirectoryID = t3.SubjectID
WHERE 
(
    ((t4.LastName LIKE 'smith%') AND (t4.FirstName LIKE 'jane%')) 
    OR ((t5.LastName LIKE 'smith%') AND (t5.FirstName LIKE 'jane%')) 
    OR ((t3.ChildNextFriendLastName LIKE 'smith%') AND (t3.ChildNextFriendFirstName LIKE 'jane%')) 
    OR (
            -- ***************
            -- THIS GUY KILLS THE QUERY WHEN A TOP IS INTRODUCED IN THE TOP-LEVEL SELECT
            -- ***************
            EXISTS(
                    SELECT NULL AS EMPTY
                    FROM dbo.Child AS t6
                    WHERE (t6.LastName LIKE 'smith%') AND (t6.FirstName LIKE 'jane%') AND (t6.DocketID = t3.DocketID)
            )
    )
)
ORDER BY t3.DocketNumber

覆盖“跳过”方法,仅检查输入是否为零。 对于除零以外的任何值,请调用原始的skip方法。 对于零不要。

因此,如果您修改dynamic.cs中提供的“跳过”,则可以执行以下操作:

    public static IQueryable Skip(this IQueryable source, int count)
    {
        if (count == 0)
        {
            return source;
        }
        if (source == null) throw new ArgumentNullException("source");
        return source.Provider.CreateQuery(
            Expression.Call(
                typeof(Queryable), "Skip",
                new Type[] { source.ElementType },
                source.Expression, Expression.Constant(count)));
    }

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM