简体   繁体   English

PagedList使用LINQ Skip and Take,但使用Count of results显示分页

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

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函数来获取当前页面上需要显示的行数,但我仍然希望根据过滤器的总计数来分页链接以显示页面。

Eg: 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. 例如:我的搜索过滤器找到50个结果,但由于我每页的行数是10个项目,我使用LINQ的Skip()和Take()只返回10行。 I still need to show in my View.cshtml the page links << 1 | 我仍然需要在我的View.cshtml中显示页面链接<< 1 | 2 | 2 | 3 | 3 | 4 | 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. 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. 这是我的Action方法的代码。 The code is getting the correct results but the pagination is not working as I need it to be: 代码获得了正确的结果,但分页不起作用,因为我需要它:

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. 以下是View中处理分页的代码段。 I looked into the project's Github site but could not find an extension method to provide custom pages. 我查看了项目的Github网站,但找不到提供自定义页面的扩展方法。 I think it will only render number of pages based on 'items per page' and the Count() of products in the @Model: 我认为它只会根据“每页的项目数”和@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>

I had the exactly same problem and I ended up using StaticPagedList. 我有完全相同的问题,我最终使用StaticPagedList。 You can do something like this 你可以做这样的事情

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>

ToPagedList uses Take and Skip internally and when you use the extension to the IQueryable<T> class, that will result in the database query you require. ToPagedList内部使用TakeSkip ,当您使用IQueryable<T>类的扩展时,这将导致您需要的数据库查询。 It also retrieves the TotalItemCount into its Metadata. 它还将TotalItemCount检索到其元数据中。

Sometimes you may need to bring the query results into memory because you are using a method that cannot be translated into sql. 有时您可能需要将查询结果带入内存,因为您使用的方法无法转换为sql。 That means you have to convert the PagedList back to an Enumerable . 这意味着您必须将PagedList转换回Enumerable You can get around this problem by using the StaticPagedList method like this: 您可以通过使用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类的新实例,该实例包含已划分的子集以及有关超集大小和子集在其中的位置的信息。

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

If you use PagedList's methods, you do not need to also use LINQ .skip() and .take() . 如果使用PagedList的方法,则不需要使用LINQ .skip().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 pagesize results by .skip() and .take() then passing those pagesize results to be filtered again down to pagesize , which will of course be the same, but then PagedList doesn't know what the total is. 如果你这样做,那么你是预先限制列表,使用库是没有意义的,因为你首先过滤列表以通过.skip().take()获取pagesize结果,然后将这些pagesize结果传递给再次过滤到pagesize ,这当然是相同的,但是然后PagedList不知道总数是多少。

If you want to ensure you are not loading all results, simply send an IQueryable to PagedList instead of an Enumerable or List . 如果要确保未加载所有结果,只需将IQueryable发送到PagedList而不是EnumerableList PagedList will add the .Skip() and .Take() for you, and your database will only return those results. PagedList将添加.Skip().Take()为你和你的数据库将只返回这些结果。

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); 或新的StaticPagedList(产品,页面,PageSize,count * pagesize);

thus it provide all available counts in pages. 因此它提供页面中的所有可用计数。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM