【问题标题】:How do I make a real pagination using PagedList?如何使用 PagedList 进行真正的分页?
【发布时间】:2018-02-06 18:29:15
【问题描述】:

我在数据库中有一个包含 10.000 条记录的表,我想使用 PagedList 对其进行分页。问题是所有记录都已加载,然后 PagedList 对它们进行分页,它变得非常慢。我想做一个真正的分页,例如将每 20 条记录返回到 10.000 并在视图中显示它们,但我做不到。

我怎么能这样做?有什么例子吗?

模型搜索

public class SearchUsuario
{
    public IPagedList<ViewUsuario> lista { get; set; }
    public SearchUsuario(){
        lista = new List<ViewUsuario>().ToPagedList(1, 50);
    }
}

Model ViewUsuario

public class ViewUsuario
{
    public String nome { get; set; }
}

通用 DAO

//returns all records
public IQueryable<T> GetAll()
{
    IQueryable<T> query = context.Set<T>();
    return query;
}

控制器

public ActionResult view(int? page)
{
    int pageNumber = page ?? 1;
    int pageSize = 10;
    SearchUsuario search = new SearchUsuario();
    IQueryable<Usuario> lista = new UsuarioDAO().GetAll(); //returns all records
    List<ViewUsuario> listaModel = new List<ViewUsuario>();
    foreach(Usuario u in lista){
        Debug.WriteLine(u.nome);
        ViewUsuario view = new ViewUsuario();
        view.nome = u.nome;
        listaModel.Add(view);
    }
    search.lista = listaModel.ToPagedList(pageNumber, pageSize);
    return View(search);
}

查看

@using PagedList.Mvc
@model SearchUsuario
....   
<table id="grid" class="table table-striped table-hover" cellspacing="0">
    <thead>
        <tr>
            <th>Nome</th>
        </tr>
    </thead>
    <tfoot>
        <tr>
            <th>Nome</th>
        </tr>
    </tfoot>
    <tbody>  
        @foreach (ViewUsuario m in Model.lista){
            <tr>
                <td>@Html.DisplayFor(i => m.nome)</td>
            </tr>
        }                         
    </tbody>
</table>
....
Pagina @Model.lista.PageNumber de @Model.lista.PageCount
@Html.PagedListPager(Model.lista, page => Url.Action("view", new{ page = page }))

【问题讨论】:

  • 您需要将您的数据库查询调整为.Skip().Take()。您将根据页码和页面大小计算分页值。
  • 我认为你的问题出在你的 new UsuarioDAO().GetAll() 句子中:如果你使用 IQueryable,你需要返回一个 IQueryable 而不是一个物化集合(如 ListArray),你可以使用ToPagedList 将搜索范围缩小到页面中所需的项目,因此如果您发布该类的代码会很有帮助
  • @Jasen 用作您的链接建议它可以工作,但在 View 上不显示页面索引。例如:第 2 页、第 3 页、第 4 页...等。我需要 2 个 List 或者一个 Count 与记录数来创建这个?
  • @xavvvier UsuarioDAO.GetAll() 返回一个 IQueryable,请参见:` public IQueryable GetAll(){ IQueryable query = context.Set();返回查询; }`

标签: asp.net-mvc pagedlist


【解决方案1】:

.ToPagedList() 方法内部调用.Skip().Take() 以将结果集限制为指定的记录数。但是,它旨在获取您的数据模型的IQueryable&lt;T&gt;,而不是为视图模型设计的。

您的问题是您使用IQueryable&lt;Usuario&gt; 并使用循环为数据库中的每条记录生成视图模型,因此您不仅将 10,000 条记录下载到内存中,还在内存中创建了 10,000 个视图模型(以及然后你扔掉其中的 9,990 个)

根据您显示的代码,您不需要视图模型。相反,您可以简单地使用

public ActionResult view(int? page)
{
    int pageNumber = page ?? 1;
    int pageSize = 10;
    IQueryable<Usuario> lista = new UsuarioDAO().GetAll();
    SearchUsuario search = new SearchUsuario
    {
        lista = lista.ToPagedList(pageNumber, pageSize);
    };
    return View(search);
}

并将SearchUsuario中的属性更改为

public IPagedList<Usuario> lista { get; set; }

ToPagedList() 方法现在只会下载视图中所需的 10 条记录。

对于确实需要视图模型的情况,您需要使用StaticPagedList 方法并将记录总数传递给它,以便正确呈现视图中的页码按钮。这意味着第二次数据库调用来获取记录的.Count(),但这通常非常快

public ActionResult view(int? page)
{
    int pageNumber = page ?? 1;
    int pageSize = 10;
    // Get the count of all records
    int totalRecords = IQueryable<Usuario> lista = new UsuarioDAO().GetAll().Count();
    // Get just the records to be displayed using .Skip() and .Take()
    // and project into your view model
    IEnumerable<ViewUsuario> lista = new UsuarioDAO().GetAll()
        .OrderBy(u => u.nome).Skip(pageSize * pageNumber).Take(pageSize)
        .Select(x => new ViewUsuario
        {
            nome = x.nome,
            ....
        });
    SearchUsuario search = new SearchUsuario
    {
        lista = new StaticPagedList<ViewUsuario>(lista, pageNumber, pageSize, totalRecords);
    }
    return View(search);
}

【讨论】:

  • 我需要在 HTML 上更改一些内容?
  • 您的视图代码看起来不错。你有什么问题?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-09-04
  • 2019-10-02
  • 2020-10-01
  • 2013-09-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多