Force LINQ to SQL to use RowNumber() instead of Top n When Using .Skip(0)
Is there a way to force LINQ to SQL to avoid using TOP X when using Skip(0)? I have a query that runs just fine for every paged result...except for page 1. I've profiled the query and the introduction of a TOP clause just kills it. I'm perplexed on why that is, but it just does. However, using RowNumber Between 1 AND 10 works just fine.
Is there a way to force LINQ to SQL to avoid using TOP X when using Skip(0)? I have a query that runs just fine for every paged result...except for page 1. I've profiled the query and the introduction of a TOP clause just kills it. I'm perplexed on why that is, but it just does. However, using RowNumber Between 1 AND 10 works just fine.
The culprit seems to be an EXISTS condition in my WHERE clause. The produced SQL is below. In SQL Manager, this q开发者_如何学Cuery runs fine and returns 14 results...however it times out once I add a TOP 10 (as LINQ would do). However, if I comment the EXISTS in my where clause, then the problem goes away.
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
Override the Skip method and just check the input for zero. For any value but zero call the original skip method. For zero don't.
so if you modify the Skip provided in dynamic.cs you could do:
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)));
}
精彩评论