Заставить LINQ to SQL использовать RowNumber () вместо Top n при использовании .Skip (0) - PullRequest
2 голосов
/ 04 августа 2011

Есть ли способ заставить LINQ to SQL избежать использования TOP X при использовании Skip (0)?У меня есть запрос, который прекрасно работает для каждого постраничного результата ... за исключением страницы 1. Я профилировал запрос, и введение предложения TOP просто убивает его.Я озадачен, почему это так, но это так.Тем не менее, использование RowNumber между 1 и 10 прекрасно работает.

Есть ли способ заставить LINQ to SQL избежать использования TOP X при использовании Skip (0)?У меня есть запрос, который прекрасно работает для каждого постраничного результата ... за исключением страницы 1. Я профилировал запрос, и введение предложения TOP просто убивает его.Я озадачен, почему это так, но это так.Тем не менее, использование RowNumber между 1 и 10 прекрасно работает.

В моем предложении WHERE виновником является условие EXISTS.Произведенный SQL ниже.В SQL Manager этот запрос работает нормально и возвращает 14 результатов ... однако он истекает, как только я добавляю TOP 10 (как это сделает LINQ).Однако, если я прокомментирую EXISTS в моем предложении where, проблема исчезнет.

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

1 Ответ

1 голос
/ 04 августа 2011

Переопределите метод Пропустить и просто проверьте вход на ноль. Для любого значения, кроме нуля, вызовите оригинальный метод пропуска. Для нуля не надо.

, поэтому, если вы измените Пропуск, предоставленный в 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)));
    }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...