Я использую LINQ to Entities для отображения постраничных результатов. Но у меня проблемы с комбинацией вызовов Skip()
, Take()
и OrderBy()
.
Все работает нормально, за исключением того, что OrderBy()
назначен слишком поздно. Он выполняется после того, как набор результатов был сокращен на Skip()
и Take()
.
Таким образом, каждая страница результатов имеет элементы по порядку. Но упорядочение выполняется на нескольких страницах данных вместо упорядочивания всего набора, а затем ограничивается этими записями Skip()
и Take()
.
Как установить приоритет для этих утверждений?
Мой пример (упрощенный)
var query = ctx.EntitySet.Where(/* filter */).OrderByDescending(e => e.ChangedDate);
int total = query.Count();
var result = query.Skip(n).Take(x).ToList();
Одно возможное (но плохое) решение
Одним из возможных решений было бы применение кластерного индекса к порядку по столбцу, но этот столбец часто меняется, что снижает производительность базы данных при вставках и обновлениях. И я действительно не хочу этого делать.
EDIT
Я выполнил ToTraceString()
в моем запросе, где мы можем увидеть, когда order by применяется к результирующему набору. К сожалению в конце. (
SELECT
-- columns
FROM (SELECT
-- columns
FROM (SELECT -- columns
FROM ( SELECT
-- columns
FROM table1 AS Extent1
WHERE EXISTS (SELECT
-- single constant column
FROM table2 AS Extent2
WHERE (Extent1.ID = Extent2.ID) AND (Extent2.userId = :p__linq__4)
)
) AS Project2
limit 0,10 ) AS Limit1
LEFT OUTER JOIN (SELECT
-- columns
FROM table2 AS Extent3 ) AS Project3 ON Limit1.ID = Project3.ID
UNION ALL
SELECT
-- columns
FROM (SELECT -- columns
FROM ( SELECT
-- columns
FROM table1 AS Extent4
WHERE EXISTS (SELECT
-- single constant column
FROM table2 AS Extent5
WHERE (Extent4.ID = Extent5.ID) AND (Extent5.userId = :p__linq__4)
)
) AS Project6
limit 0,10 ) AS Limit2
INNER JOIN table3 AS Extent6 ON Limit2.ID = Extent6.ID) AS UnionAll1
ORDER BY UnionAll1.ChangedDate DESC, UnionAll1.ID ASC, UnionAll1.C1 ASC