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);

таким образом, он предоставляет все доступные значения на страницах.