2012-04-13 5 views
9

Есть ли способ получить количество строк сложного запроса Linq и миллионы записей без ударить по db дважды или написать 2 отдельных запроса?C# Entity Framework Pagination

У меня может быть собственное предложение. Напишите хранимую процедуру, но я хорошо разбираюсь в MySQL, а не в MSSQL.

Любые лучшие предложения были бы замечательными. Кроме того, если кто-нибудь знает, работает ли Microsoft над добавлением этой функции в инфраструктуру сущности.

+3

Я вполне уверен, что вы не можете получить количество строк в своем запросе без попадания в базу данных или написания запроса отдельно от того, который фактически возвращает эти строки. –

+0

Спасибо @JonathanWood за ваши мысли! –

+1

Когда вы используете .Count() в EF, он не выбирает все строки, он выполняет только 'select count() из оператора table' sql, поэтому, когда вам нужны 2 запроса, один из них очень дешев. –

ответ

2

Обычный способ показать миллионы записей - это просто не отображать все страницы. Подумайте об этом: если у вас есть миллионы записей, скажем, 20 или даже 100 пунктов на странице, тогда у вас будет десятки тысяч страниц. Не имеет смысла показывать их всем. Вы можете просто загрузить текущую страницу и предоставить ссылку на следующую страницу, вот и все. Или вы можете загрузить, скажем, 100-500 записей, но по-прежнему показывать только одну страницу и использовать загруженные данные записей для создания ссылок на страницы для первых нескольких страниц (так что знайте, сколько доступных страниц доступно).

+0

Вы правы, я бы не хотел показывать сотни или тысячи ссылок или даже заставить кого-то пройти через многие страницы. Я предполагаю, что проблема в том, что я хочу написать только один запрос.Например: MySQL разрешил вам использовать SQL_CALC_FOUND_ROWS в запросе, а затем еще один запрос, чтобы вытащить именно этот результат. Очень эффективный!!! Сделано Pagination замечательно! Спасибо @ ВладимируПеревалову за ваши мысли! –

+0

AFAIK нет такой поддержки в LINQ ни в MS SQL Server. На самом деле есть много вещей, которые делает MySql, и MS SQL этого не делает. Например. 'SELECT BETWEEN ...' также очень эффективен для разбивки на страницы. –

+0

вы также можете предоставить текстовое поле «Перейти к:» и кнопку, чтобы перейти к конкретной странице напрямую. –

8

Я бы предложил использовать функцию Take(). Это можно использовать для указания количества записей, которые нужно взять из запроса linq или List. Например

List<customers> _customers = (from a in db.customers select a).ToList(); 
var _dataToWebPage = _customers.Take(50); 

Я использую подобный метод в приложении MVC, где я пишу список _customers к сессии, а затем использовать этот список для дальнейших запросов постраничных, когда пользователь нажимает на странице 2, 3 и т.д. Это экономит множественным обращений к базе данных. Однако, если ваш список очень велик, пишите его тоже, вероятно, это не очень хорошая идея.

Для разбивки на страницы вы можете использовать функции Skip() и Take() вместе. Например, чтобы получить страницу 2 данных:

var _dataToWebPage = _customers.Skip(50).Take(50); 
+0

Спасибо @TimNewton. Конечно, но если у меня есть миллион записей или еще еще тысяча записей с очень большими столбцами данных, вы столкнулись с исключением из памяти. –

+0

Джейсон, вы могли бы рассмотреть возможность записи первичных ключей в список в сеансе, а не весь объект, а затем извлечения данных из базы данных каждый раз, когда вам нужно повторно отображать данные, используя первичные ключи из списка? Тем не менее, это требует множественного чтения базы данных. Я не думаю, что вы можете уйти без множественного чтения db, если ваш набор данных настолько велик. –

+0

, возможно, вы правы в том, что не можете сделать один db, прочитанный для этого экземпляра, в C# и используя Linq. Я знаю, что это можно сделать, просто для того, чтобы я хотел использовать Linq для того, чтобы он был строго типизирован и идет с остальной частью моего чистого кода. У меня есть разбиение на страницы, прекрасно работающее на небольших таблицах, которые не содержат больших наборов данных или больших данных. –

2

так просто на сервере sql. вы можете написать этот запрос:

select count() over(), table.* from table 

Граф() над() возвращает количество общего ряда в результате, так что вам не нужно запускать два запроса .. Помните, что вы должны запустить сырец sql в вашем контексте или использовать dapper, который возвращает результат в виде модели представления