Subsonic 3.0.0.3 SQL Paging с использованием Linq - PullRequest
3 голосов
/ 01 сентября 2009

Только что обновился с Subsonic 2.2 ActiveRecord до 3.0.0.3. Я пытаюсь использовать LINQ для выполнения постраничного запроса Find, подобного этому (мой объект / таблица называется «Репозиторий»):

Repository.Find(item => item.DocumentTitle.Contains(searchTerm))
    .OrderBy(i => i.DocumentTitle).Skip((currentPage - 1) * itemsPerPage)
    .Take(itemsPerPage);

Когда я просматриваю SQL, сгенерированный этим запросом, используя SQL Server Profiler, в SQL нет подкачки, все подкачки выполняются в памяти в C #. Теперь у языка запросов Subsonic есть хорошая процедура GetPaged, которая работает правильно, но я подумал, что LINQ должен был делать это тоже. Я что-то здесь упустил или это ограничение LINQ?

Мне известна функция Repository.GetPaged(), но у нее недостаточно параметров - мне нужно выполнить динамическую сортировку, а также Find().

Ответы [ 3 ]

5 голосов
/ 03 сентября 2009

После дальнейшего тестирования это утверждение работает правильно:

(from i in dataContext.Repositories 
 where i.DocumentTitle.Contains(searchTerm) 
 orderby i.DateCreated ascending select i)
 .Skip((currentPage - 1) * itemsPerPage).Take(itemsPerPage);

При выполнении вышеприведенный оператор linq возвращается должным образом в SQL.

Единственный вывод, к которому я могу прийти, это то, что когда вы используете синтаксис цепочки методов, как только вы выходите за пределы исходного выражения лямда

Repository.Find(item => item.DocumentTitle.Contains(searchTerm))

дозвуковой интерпретатор SQL прекращает создание SQL для любых методов, связанных в конец

.OrderBy(i => i.DocumentTitle).Skip(15).Take(10);

Или я просто что-то здесь не так делаю? У кого-нибудь есть понимание?

1 голос
/ 01 сентября 2009

Вы можете отсортировать GetPaged, добавив «desc» в поле сортировки, но ...

Пейджинг должен работать - я смотрю на SQL-пейджинг передо мной, и он не выполняется в памяти. Как вы это тестируете? Если вы используете «ToList ()», который будет выполнять запрос - взгляните на профилировщик.

0 голосов
/ 07 октября 2010

Немного поздно, но ...

Repository.Find()

возвращает IList, поэтому запрос выполняется, следовательно, SQL выполняется без подкачки, тогда

.Skip(x).Take(x)

делается в памяти. Попробуйте

Repository.All().Where(expression).Skip(x).Take(x)

все из которых возвращают IQueryable, а не перечисляют объекты, поэтому подкачка страниц выполняется в SQL с использованием функции ROW_NUMBER ().

Сказав, что Subsonic 3 простой репозиторий генерирует следующий SQL

exec sp_executesql N'SELECT [t0].[Id], [t0].[IsDeleted], [t0].[Name], [t0].[ParentUuid], [t0].[Uuid]
FROM ( SELECT [t1].[Id], [t1].[IsDeleted], [t1].[Name], [t1].[ParentUuid], ROW_NUMBER() OVER() AS rownum, [t1].[Uuid]
FROM [Sites] AS t1
WHERE (([t1].[ParentUuid] = @p0) AND ([t1].[IsDeleted] = 0))) AS t0
WHERE [t0].[rownum] BETWEEN (20 + 1) AND (20 + 10)',N'@p0 uniqueidentifier',@p0='00000000-0000-0000-0000-000000000000'

который выдает исключение

Unhandled Exception: System.Data.SqlClient.SqlException: The ranking function "ROW_NUMBER" must have an ORDER BY clause.

так что может показаться, что в Subsonic есть ошибка: - (

...