2014-05-07 15 views
3

现在我正在将我的模型中的列表返回给视图。该清单包含300k项目。MVC如何为大型结果集添加分页

我做这样的事情

<table> 
     <thead> 
      <tr> 
       <th>First Name</th> 
       <th>Last Name</th> 
       <th>E-mail</th> 
       <th>Role</th> 
      </tr> 
     </thead> 
     <tbody> 
      @foreach (var user in Model) { 
       <tr> 
        <td>@user.FirstName</td> 
        <td>@user.LastName</td> 
        <td>@user.Email</td> 
        <td>@user.UserRole.UserRoleName</td> 
       </tr> 
      } 
     </tbody> 
    </table> 

所以你们的问题是,它需要永远载入显示300K项目的页面,再加上所有的滚动是一个问题。 MVC中有更好的解决方案来处理这个问题并添加自动分页等吗?

+0

你会想要使用某种jQuery网格。例如,jqGrid。 –

回答

0

我发现,当数据集变得太大时,后端和前端都会只抓取我需要呈现整个数据集的子集的数据。在LINQ中,它将是一个.Skip。获取所需的分页数据。

0

虽然@ marcusking2002提供的答案是正确的,但有一些功能强大的jQuery网格组件可以为用户提供更丰富的用户体验并为您节省大量手动格式。

这些包括jqGrid http://www.trirand.com/blog/,flexigrid http://www.flexigrid.info/(免费选项),或者如果你想要一些现金,那么剑道的产品http://www.telerik.com/kendo-ui是非常强大的。

还有其他的,这些都是简单的人,我用:)

4

解决方法有很多,在那里,可以帮助你棘手的问题是,没有人会完全解决。我要说的是,他们将帮助客户端,与分页组件和网格显示数据,甚至无尽的滚动(如Facebook时间,加载N更多的recods,按需)。有些人还会在服务器端帮助你。

但由于它与您的数据源和数据结构太相关,因此没有“有效所有情况”解决方案。

我有大约10个生产阶段的大规模ASP.NET MVC项目,并不是每个人都拥有相同的技术。他们大多使用jQuery DataTables,它是一个整合的jquery插件,可以帮助你做很多事情,包括排序,过滤,当然还有服务器端分页。在我的答案的最后,你会发现一些链接到DataTables和我在GitHub上的项目,这有助于服务器端,以及一些其他有趣的链接。

最近我们已经转向Angular(来自Google团队)。它有一个内置的网格机制(你可以使用其他的,如果你喜欢的话),称为ngGrid,它也支持分页,过滤和排序。

波纹考虑代码为“动作模板”,这将有助于您了解如何开始使用服务器端分页(我假设你正在使用EF这个样品的缘故):

public JsonResult Paginate(int page, int recordsPerPage, string filter, string[] sorting) 
{ 
    // 1. count total (non-filtered) data from your database. 
    var _total = context.Entities.Count(); 

    // 2. count filtered (available) record set 
    var _filtered = context.Entities.Where(_e => _e.Description.ToLower().Contains(filter)).Count(); 

    // 3. retrieve only desired page, here follows some linq sample if you're using EF 
    // I'm assuming your page count starts with 1 (natural counting), that's why I'm subtracting 
    // one from the current page number 
    var _page = context.Entities.Where(_e => _e.Description.ToLower().Contains(filter)).OrderBy(_e => _e.Description).Skip((page - 1) * recordsPerPage).Take(recordsPerPage); 

    // 4. Return a json object (or view result with all counters and data to display) 
    return Json(new { TotalRecords = total, FilteredRecords = filtered, Records = _page }); 
} 

请记住,为了便于使用,我不处理排序集合。当然,您应该这样做,以便您的最终用户可以通过简单的方式对所有数据进行分类。现在

,从您的客户端,你将不得不请求(AJAX,我建议,以获取可能的话只需要数据)的方式类似:

<script> 
    $.ajax({ 
     url: "/my/route", 
     data: { page: _page, recordsPerPage: _recordsPerPage, filter: _filter, sorting: _sorting }, 
     method: "POST", 

     success: function(jsonResult) { /* update your data on grid/table/div/etc */ }, 

     error: function(errorResult) { console.log(errorResult); /* temporary, so you may find out what happened*/ } 
    }); 
</script> 

请考虑_page是一个变量,其中包含“下一个所需页面”,可能是第一个,上一个,下一个,最后一个页面或特定的一个(最常见的情况),_recordsPerPage是一个变量,当用户选择从下拉菜单中选择更大(或更小)的页面大小,_filtertext-inputblur事件中得到更新的字符串,而_sorting是字符串数组,其中您的商店d希望排序。

通常插件(如DataTables,jqGrid等)将为您填充这些变量或为您提供获取这些变量的方法。

作为可用性的一般规则,从不为最终用户返回超过20条记录,除非他/她明确地另有说明(例如:通过从下拉列表中选择每页记录值)。您将避免来自数据库的不必要的负载,不必要的链接消耗和您的页面加载速度要快得多。

另一个建议我会做是创建一个辅助类为您的分页,所以你总是有一个标准,如:

public class PageViewModel<TEntity> 
{ 
    public int TotalCount { get; private set; } 
    public int FilteredCount { get; private set; } 
    public IEnumerable<TEntity> Records { get; private set; } 
    public int RecordsPerPage { get; private set; } 

    // Help with some jQuery libs to help counting the number of pages to display... 
    public int AvailablePages { get; private set; } 

    /* Constructor */ 
} 

这样你可以创建某种通用的局部视图的显示数据,无论您的页面返回的实体类型如何。

但所有这些可能会改变,这取决于你使用的是什么。例如,如果使用纯粹的ADO.NET,则必须为相同的SKIP/TAKE方法处理不同的SQL语法,并且该实现可能会从数据库版本更改。 2008之前的MSSQL不会帮助你分页。

如果您使用Dapper(这是StackOverflow的下ORM),你可以写你的分页SQL或进行一个推广使用,像DapperExtensionsRainbowDapper.Contrib这将与分页花哨的方法都没有帮助即SQL语法的东西。

如果您进入EF,您只需使用LinqToEntities并且它已全部设置。从我所知道的NHibernate(从未实际使用过),应该与LinqToNHibernate类似。

此外,如果您使用(或不)存储库,则可能会更改。对你而言,你的控制器可以简单地将页面解析委托给你的仓库并以集中的方式记录获取。如果没有,你最终会得到很多重复的代码或者到处都有很多助手。

但是,如果你不是到JavaScript,你可以使它的所有工作与普通的ASP.NET MVC。你会有更多的工作,但是是的,这是可能的。

无论如何,这里有一些链接,可以帮助你: