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

时间:2013-11-12 23:48:06

标签: c# linq asp.net-mvc-4 pagination pagedlist

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

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

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

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

**我的目标是为数据库编写优化查询,以便网页响应速度快。

以下是我的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));
}

以下是View中处理分页的代码段。我查看了项目的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>

5 个答案:

答案 0 :(得分:24)

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

答案 1 :(得分:3)

ToPagedList在内部使用TakeSkip,当您使用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类的新实例   包含已经划分的子集和有关的信息   超集的大小和子集在其中的位置。

答案 2 :(得分:2)

你仍然可能需要单独索要一个计数。

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

答案 3 :(得分:2)

如果使用PagedList的方法,则无需使用LINQ .skip().take()。如果你这样做,那么你是预先限制列表,使用库是没有意义的,因为你首先过滤列表以pagesize.skip()获得.take()结果然后将那些pagesize结果再次过滤到pagesize,这当然会是相同的,但是然后PagedList不知道总数是多少。

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

答案 4 :(得分:0)

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

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

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

如果要显示所有页面链接可用数量, 然后

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

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