如何使用 PagedList 进行真正的分页?

How do I make a real pagination using PagedList?

我在数据库中有一个 table,有 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 }))

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

您的问题是,您使用 IQueryable<Usuario> 并使用循环为数据库中的每条记录生成视图模型,因此您不仅将 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);
}