C# PagedList 使用 LINQ Skip and Take,但使用结果计数显示分页

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/19942395/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-10 16:10:47  来源:igfitidea点击:

PagedList using LINQ Skip and Take, but show paging using Count of results

c#linqasp.net-mvc-4paginationpagedlist

提问by badboy11

I am trying to display a filtered list of of products, based on Category filter and ItemsPerPage but I'm having some issues when trying to use it with PagedList.

我正在尝试根据类别过滤器和 ItemsPerPage 显示过滤的产品列表,但在尝试将它与 PagedList 一起使用时遇到了一些问题。

Someone with PagedList expertise could advice me if I need to write my own pagination code or is there a way to get the results I need using PagedList.

如果我需要编写自己的分页代码,或者有没有办法使用 PagedList 获得我需要的结果,那么具有 PagedList 专业知识的人可以建议我。

I am using LINQ's Skip & Take functions to get only the number of rows that need to be displayed on the current page, but I would still like paging links to show pages based on the filter's total count.

我正在使用 LINQ 的 Skip & Take 函数来仅获取需要在当前页面上显示的行数,但我仍然希望分页链接根据过滤器的总数显示页面。

E.g.:my search filter finds 50 results, but since my rows per page is say 10 items, I use LINQ's Skip() & Take() to get only 10 rows back. I still need to show in my View.cshtml the page links << 1 | 2 | 3 | 4 | 5 >>Right now with default PagedList, I only get << 1 >>, I know why I only see one page but just wanted to know how can I make it work to show correct number of page links, while only getting a subset of results.

例如:我的搜索过滤器找到 50 个结果,但由于我每页的行是 10 个项目,我使用 LINQ 的 Skip() 和 Take() 只返回 10 行。我仍然需要在我的 View.cshtml 中显示页面链接<< 1 | 2 | 3 | 4 | 5 >>现在使用默认的 PagedList,我只得到<< 1 >>,我知道为什么我只看到一页,但只是想知道如何让它显示正确数量的页面链接,同时只得到一个子集结果。

**My goal is to write optimized queries to the Database so the web page response performance will be fast.

**我的目标是将优化的查询写入数据库,这样网页响应性能就会很快。

Here is what my code for the Action Method looks like. The code is getting the correct results but the pagination is not working as I need it to be:

这是我的 Action Method 代码的样子。代码得到了正确的结果,但分页无法正常工作,因为我需要它:

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

Here is the code snippet from the View that deals with pagination. I looked into the project's Github site but could not find an extension method to provide custom pages. I think it will only render number of pages based on 'items per page' and the Count() of products in the @Model:

这是处理分页的视图中的代码片段。我查看了该项目的 Github 站点,但找不到提供自定义页面的扩展方法。我认为它只会根据“每页项目数”和@Model 中产品的 Count() 来呈现页数:

@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>

回答by Michael Dunlap

You will still likely have to ask for a count separately.

您仍然可能需要单独要求计数。

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

回答by solidau

If you use PagedList's methods, you do not need to also use LINQ .skip()and .take(). If you do, then you are pre-limiting the list, and it would be pointless to use the library because you are first filtering down the list to get pagesizeresults by .skip()and .take()then passing those pagesizeresults to be filtered again down to pagesize, which will of course be the same, but then PagedList doesn't know what the total is.

如果使用 PagedList 的方法,则不需要同时使用 LINQ.skip().take(). 如果这样做,那么您正在预先限制列表,并且使用该库将毫无意义,因为您首先过滤列表以获取pagesize结果.skip().take()然后将这些pagesize结果再次向下过滤到pagesize,这当然会是一样的,但是 PagedList 不知道总数是多少。

If you want to ensure you are not loading all results, simply send an IQueryableto PagedList instead of an Enumerableor List. PagedList will add the .Skip()and .Take()for you, and your database will only return those results.

如果您想确保没有加载所有结果,只需将 发送IQueryable到 PagedList 而不是EnumerableList。PagedList 将为您添加.Skip().Take(),您的数据库将只返回这些结果。

回答by mpricochi

I had the exactly same problem and I ended up using StaticPagedList. You can do something like this

我遇到了完全相同的问题,最终使用了 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);
}

as for the view, you just need to replace the model type

至于视图,你只需要替换模型类型

@model StaticPagedList<Product>

回答by Abhi

The above explanation is correct. But when you are assigning Static select list..

上面的解释是正确的。但是当您分配静态选择列表时..

new StaticPagedList<Product>(products, page, PageSize, count);.

It displays less number of page link from actual count. If Count is 10 it show only 2 pages if your page size is 5..

它显示的页面链接数比实际计数少。如果 Count 为 10,则如果您的页面大小为 5,则仅显示 2 页。

If you want to show all pages link availabe in count, then

如果你想显示所有可用的页面链接计数,那么

pass count*5 ie count*pagesize

new StaticPagedList<Product>(products, page, PageSize, count*5);//in my case page size is 5

or new StaticPagedList(products, page, PageSize, count*pagesize);

或 new StaticPagedList(products, page, PageSize, count*pagesize);

thus it provide all available counts in pages.

因此它提供了所有可用的页数。

回答by Colin

ToPagedListuses Takeand Skipinternally and when you use the extension to the IQueryable<T>class, that will result in the database query you require. It also retrieves the TotalItemCountinto its Metadata.

ToPagedList在内部使用TakeSkip,当您使用IQueryable<T>类的扩展时,将产生您需要的数据库查询。它还将 检索TotalItemCount到其元数据中。

Sometimes you may need to bring the query results into memory because you are using a method that cannot be translated into sql. That means you have to convert the PagedListback to an Enumerable. You can get around this problem by using the StaticPagedListmethod like this:

有时您可能需要将查询结果带入内存,因为您使用的是无法转换为 sql 的方法。这意味着您必须将PagedListback转换为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());
}

From the summary of the method in comments:

从评论中的方法摘要:

Initializes a new instance of the PagedList.StaticPagedList class that contains the already divided subset and information about the size of the superset and the subset's position within it.

初始化 PagedList.StaticPagedList 类的新实例,该类包含已划分的子集以及有关超集大小和子集在其中的位置的信息。