Linq的延迟执行与MVC的分页

一条Linq语句,比如下面用于返回一个Dinner对象集合的查询

private NerdDinnerDataContext db = new NerdDinnerDataContext();

public IQueryable<Dinner> FindUpcomingDinners()
{
    return from dinner in db.Dinners
           where dinner.EventDate > DateTime.Now
           orderby dinner.EventDate
           select dinner;
}

这条“select”只有当它在的数据被访问或者迭代,又或者是ToList()方法被调用的时候,才会真正向数据库提交。该函数必须返回IQueryable<>类型,这样方便于我们应用点连接式Linq查询,来筛选结果集中的数据。

下面我们来看看如何利用它来实现MVC的分页机制。

我们按照设定的pageSize对数据进行服务端分页,实际上就是把结果集进行窗口筛选,然后回送给用户。

public ActionResult Index(int? page)
{
    const int pageSize = 10;

    var upcomingDinners = this.dinnerRepository.FindUpcomingDinners();
    var paginatedDinners = upcomingDinners.Skip((page ?? 0) * pageSize)
                                          .Take(pageSize)
                                          .ToList();

    return View(paginatedDinners);
}

从Model传递过来的结果集,通过Skip()和Take()两个动作,筛选出我们需要的那一页结果。注意这个查询是会被进行优化的。

要想访问某一页,需要在URL中以?参数的形式给出,比如/Dinners?page=1。但这样做并非SEO最优,我们还需要将其转换成常规URL,并且将参数嵌入进去。为此,MVC强大的路由功能就派上用场了。在Global.asax的后台代码中,加入这条路由的注册:

public static void RegisterRoutes(RouteCollection routes)
{
    routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

    routes.MapRoute(
        "UpcomingDinners",
        "Dinners/Page/{page}",
        new { controller = "Dinners", action = "Index" }
    );

    routes.MapRoute(
        "Default",                                              // Route name
        "{controller}/{action}/{id}",                           // URL with parameters
        new { controller = "Home", action = "Index", id = "" }  // Parameter defaults
    );

}

这样就可以将?参数转化为URL的一部分,至此,分页就搞定了。

posted @ 2009-12-29 19:43  Jacky Zhou  阅读(486)  评论(0编辑  收藏  举报