PagedList с использованием LINQ Skip и Take, но показ пейджинга с использованием Count of results
Я пытаюсь отобразить отфильтрованный список продуктов на основе фильтра категорий и ItemsPerPage, но у меня возникают некоторые проблемы при попытке использовать его с PagedList.
Кто-то с опытом PagedList может посоветовать мне, если мне нужно написать свой собственный код разбивки на страницы или есть способ получить результаты, которые мне нужны, используя PagedList.
Я использую функции LINQ Skip и Take, чтобы получить только количество строк, которые должны отображаться на текущей странице, но мне все равно понравятся пейджинговые ссылки для отображения страниц на основе общего количества фильтров.
Например: мой фильтр поиска находит 50 результатов, но поскольку мои строки на странице говорят 10 элементов, я использую LINQ Skip() и Take(), чтобы получить только 10 строк назад. Мне все еще нужно показать в моем View.cshtml ссылки на страницы < < 1 | 2 | 3 | 4 | 5 →
Прямо сейчас с PagedList по умолчанию, я получаю только < < 1 → . Я знаю, почему я вижу только одну страницу, но просто хочу знать, как я могу заставить ее работать, чтобы показать правильное количество ссылок на страницы, а только получить подмножество результатов.
** Моя цель - написать оптимизированные запросы в базу данных, чтобы производительность реакции веб-страницы была быстрой.
Вот как выглядит мой код для Action Action. Код получает правильные результаты, но разбиение на страницы не работает так, как мне нужно:
public ViewResult List(int page =1, string category =null)
{
if (category != null) this.CurrentCategory = category;
var products = repository.Products
.Where(p => this.CurrentCategory == null || p.Category == this.CurrentCategory)
.OrderBy(p => p.ProductID)
.Skip((page -1) * PageSize)
.Take(PageSize);
return View(products.ToList().ToPagedList(page, PageSize));
}
Вот фрагмент кода из представления, который связан с разбиением на страницы. Я просмотрел сайт Github проекта, но не смог найти метод расширения для предоставления настраиваемых страниц. Я думаю, что он будет отображать только количество страниц на основе "элементов на странице" и Count() продуктов в @Model:
@model IPagedList<Product>
//foreach loop that renders the @Model
//Code that displays the pagination using PagedList
<div style="text-align:center">
@Html.PagedListPager(Model, page => Url.Action("List", new { page = page, category = ViewBag.CurrentCategory }), PagedListRenderOptions.OnlyShowFivePagesAtATime
)
</div>
Ответы
Ответ 1
У меня была точно такая же проблема, и я закончил использование StaticPagedList. Вы можете сделать что-то вроде этого
public ViewResult List(int page =1, string category =null)
{
if (category != null) this.CurrentCategory = category;
var products = repository.Products
.Where(p => this.CurrentCategory == null || p.Category == this.CurrentCategory)
.OrderBy(p => p.ProductID)
.Skip((page -1) * PageSize)
.Take(PageSize);
var count = repository.Products
.Where(p => this.CurrentCategory == null || p.Category == this.CurrentCategory).Count();
var resultAsPagedList = new StaticPagedList<Product>(products, page, PageSize, count);
return View(resultAsPagedList);
}
как для представления, вам просто нужно заменить тип модели
@model StaticPagedList<Product>
Ответ 2
ToPagedList
использует Take
и Skip
внутренне, и когда вы используете расширение для класса IQueryable<T>
, это приведет к необходимости запроса базы данных. Он также извлекает TotalItemCount
в свои метаданные.
Иногда вам может потребоваться привести результаты запроса в память, потому что вы используете метод, который не может быть переведен в sql. Это означает, что вам нужно преобразовать PagedList
обратно в Enumerable
. Вы можете обойти эту проблему, используя метод StaticPagedList
следующим образом:
var superset= repository.Products
.Where(p => this.CurrentCategory == null
|| p.Category == this.CurrentCategory)
.OrderBy(p => p.ProductID)
.ToPagedList(page, PageSize);
var subset = superset
.AsEnumerable()
.Select(p => new ProductViewModel
{
OtherData = p.UntranslateableMethod()
})
var model = new StaticPagedList<ProductViewModel>(subset,
superset.GetMetaData());
}
Из резюме метода в комментариях:
Инициализирует новый экземпляр класса PagedList.StaticPagedList который содержит уже разделенное подмножество и информацию о размер надмножества и его подмножество.
Ответ 3
Вам все равно придется запрашивать счет отдельно.
var products = repository.Products
.Where(p => this.CurrentCategory == null || p.Category == this.CurrentCategory);
var numProds = products.Count();
var mypage = products.OrderBy(p => p.ProductID)
.Skip((page -1) * PageSize)
.Take(PageSize);
Ответ 4
Если вы используете методы PagedList, вам не нужно также использовать LINQ .skip()
и .take()
. Если вы это сделаете, вы предварительно ограничиваете список, и было бы бессмысленно использовать библиотеку, потому что вы сначала фильтруете список, чтобы получить результаты pagesize
по .skip()
и .take()
, а затем передайте их pagesize
результаты будут снова отфильтрованы до pagesize
, что, конечно же, будет одинаковым, но тогда PagedList не знает, что такое сумма.
Если вы хотите, чтобы вы не загружали все результаты, просто отправьте IQueryable
в PagedList вместо Enumerable
или List
. PagedList добавит для вас .skip()
и .take()
, и ваша база данных вернет только те результаты.
Ответ 5
Вышеприведенное объяснение верное.
Но когда вы назначаете статический список выбора.
new StaticPagedList<Product>(products, page, PageSize, count);.
Он отображает меньшее количество ссылок на страницу из фактического счета.
Если Count равен 10, отображается только 2 страницы, если размер вашей страницы равен 5..
Если вы хотите показать все ссылки на страницы availabe в count,
затем
pass count*5 ie count*pagesize
new StaticPagedList<Product>(products, page, PageSize, count*5);//in my case page size is 5
или новый StaticPagedList (продукты, страница, PageSize, count * pagesize);
таким образом, он предоставляет все доступные значения на страницах.