zoukankan      html  css  js  c++  java
  • MVC3+EF4.1学习系列(三)排序 刷选 以及分页

    文章索引和简介

    上篇文章 已经做出了基本的增删改查    但这远远不足以应付实际的项目  今天讲下实际项目中 肯定会有的 排序 刷选  以及分页。 重点想多写点分页的 毕竟这个是任何时候都要有的

    而且 我会尽量把这个分页做的复杂下  这样到实际项目时 可以复制过来改改就行了~~ (这里我用的是国产的基于ScottGu的PagedList<T>类和相关方法完善的分页--MVCPager)

    是个开源的  带很多demo介绍的分页帮助类  这里说下 建议大家看下源码 这样才能进步 要不然只是个会使用插件的人~   在这里感谢下作者 ~~ 好了 开始先上效果图

    这个样式可以调~~  我的样子难看了些~~    显示当前页的索引 记录条数 还有跳转页数  等 常用分页的功能都有了

    我们可以根据姓名查找  可以点击 lastName 按姓名排序  和按发布日期排序  这就是今天要做的~

    一.排序

    public ViewResult Index(string sortOrder)
    {
    ViewBag.NameSortParm
    = String.IsNullOrEmpty(sortOrder) ? "Name desc" : "";
    ViewBag.DateSortParm
    = sortOrder == "Date" ? "Date desc" : "Date";
    var students
    = from s in db.Students
    select s;
    switch (sortOrder)
    {
    case "Name desc":
    students
    = students.OrderByDescending(s => s.LastName);
    break;
    case "Date":
    students
    = students.OrderBy(s => s.EnrollmentDate);
    break;
    case "Date desc":
    students
    = students.OrderByDescending(s => s.EnrollmentDate);
    break;
    default:
    students
    = students.OrderBy(s => s.EnrollmentDate);
    break;
    }
    return View(students.ToList());
    }

    这乱七八糟的是什么呢  我来解释下~  接受的参数sortOrder是根据什么排序   例如http://localhost:2175/Student?sortOrder=Date   就是根据时间升序排列

     我们可以先不看前两行 先看后面的

      var students = from s in db.Students
    select s;
    switch (sortOrder)
    {
    case "Name desc":
    students
    = students.OrderByDescending(s => s.LastName);
    break;
    case "Date":
    students
    = students.OrderBy(s => s.EnrollmentDate);
    break;
    case "Date desc":
    students
    = students.OrderByDescending(s => s.EnrollmentDate);
    break;
    default:
    students
    = students.OrderBy(s => s.EnrollmentDate);
    break;
    }

    先来说下 这不是把所有记录都查出来 然后再排序  因为这个是IQueryable 的  这个是将表达式树 翻译成SQL 最后再执行的  所以在后面的 根据条件刷选 分页 排序等 是不会有效率问题的   但是如果你把上面的students.tolist() 一下 则就是全部加载啦~~  因为不再是 IQueryable接口了~~  也就是说 他是在tolist时或者说 是在AsEnumerable才执行sql~~

    好 回到例子上  因为第一次访问  sortOrder一定是空的 所以switch到  students = students.OrderBy(s => s.EnrollmentDate);  默认按时间排序

    这时我们再来看这两句

    ViewBag.NameSortParm = String.IsNullOrEmpty(sortOrder) ? "Name desc" : "";
    ViewBag.DateSortParm
    = sortOrder == "Date" ? "Date desc" : "Date";

    viewBag  MVC3才有的   利用了.net4.0的 dynamic 特性~  其实这个和MVC2中的 viewdata使用方法差不多  我们在这里 设置  ViewBag.NameSortParm以及ViewBag.DateSortParm 是为了给view用的  一会儿看view就明白了~    上来由于sortOrder为空  所以 ViewBag.NameSortParm=Name desc   由于sortOrder 不等于Date 所以

    ViewBag.DateSortParm等于 Date  

    说白了  以时间排序为例  就是为了实现 点排序连接时   第一次 升序  再点就变成降序了  再点就变成升序........

    不看view 怎么解释都迷糊~~ 看view

    <tr>
        <th></th>
        <th>
            @Html.ActionLink("Last Name", "Index", new { sortOrder=ViewBag.NameSortParm })
        </th>
        <th>
            First Name
        </th>
        <th>
            @Html.ActionLink("Enrollment Date", "Index", new { sortOrder=ViewBag.DateSortParm })
        </th>
    </tr>
    

    不明白就自己做下 动动手~~ 调试几次就明白了~

    二.根据条件过滤

    这里我们做的是根据姓名刷选

    我们先在index视图下加个搜索框和搜索按钮

    @using (Html.BeginForm())
    {
    <p>
    Find by name: @Html.TextBox("SearchString")
    &nbsp;
    <input type="submit" value="Search" /></p>
    }

    我们的控制器更改为

    View Code
    public ViewResult Index(string sortOrder, string searchString)
    {
    ViewBag.NameSortParm
    = String.IsNullOrEmpty(sortOrder) ? "Name desc" : "";
    ViewBag.DateSortParm
    = sortOrder == "Date" ? "Date desc" : "Date";
    var students
    = from s in db.Students
    select s;
    if (!String.IsNullOrEmpty(searchString))
    {
    students
    = students.Where(s => s.LastName.ToUpper().Contains(searchString.ToUpper())
    || s.FirstMidName.ToUpper().Contains(searchString.ToUpper()));
    }
    switch (sortOrder)
    {
    case "Name desc":
    students
    = students.OrderByDescending(s => s.LastName);
    break;
    case "Date":
    students
    = students.OrderBy(s => s.EnrollmentDate);
    break;
    case "Date desc":
    students
    = students.OrderByDescending(s => s.EnrollmentDate);
    break;
    default:
    students
    = students.OrderBy(s => s.LastName);
    break;
    }

    return View(students.ToList());
    }

    Index方法多了个参数 SearchSring  这个参数名字是和 Html.TextBox 里的name对应着的 

    并且增加如下代码

    if (!String.IsNullOrEmpty(searchString))
    {
    students
    = students.Where(s => s.LastName.ToUpper().Contains(searchString.ToUpper())
    || s.FirstMidName.ToUpper().Contains(searchString.ToUpper()));
    }

    查看姓名里是否含有要搜索的

    这样 条件过滤就完成了

    但是有个小问题  我们一般搜索完 文本框保留搜索内容 而不是没了  所以这里需要再次借用ViewBag.Filter = searchString;  保存下值

    然后视图改为

     <p>Find by Name @Html.TextBox("searchString", ViewBag.Filter as string)</p> 

    好了 这样搜索就完了~~接下来 最重要的分页

    三.分页

    接下来是讲MVCPager

    首先 下去下载例子以及DLL  这里有个问题 就是下载的dll和mvc3不是很兼容 让我纠结了很久  要去下载mvc3的实例  然后把里面的 一个叫做MvcPager的dll找到 添加这个引用就OK了

    然后我们打开view下的config 添加命名空间 这样可以让你的view都有这个命名空间了~

      <system.web.webPages.razor>
    <host factoryType="System.Web.Mvc.MvcWebRazorHostFactory, System.Web.Mvc, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
    <pages pageBaseType="System.Web.Mvc.WebViewPage">
    <namespaces>
    <add namespace="System.Web.Mvc" />
    <add namespace="System.Web.Mvc.Ajax" />
    <add namespace="System.Web.Mvc.Html" />
    <add namespace="System.Web.Routing" />
    <add namespace="Webdiyer.WebControls.Mvc"/><!--添加这个 -->
    </namespaces>
    </pages>
    </system.web.webPages.razor>

    改造我们的控制器 如下

    View Code
      public ActionResult Index(string sortOrder,string searchString,int? page=1)
    {
    ViewBag.NameSortParm
    = string.IsNullOrEmpty(sortOrder) ? "Name desc" : "";
    ViewBag.DateSortParm
    = sortOrder == "Date" ? "Date desc" : "Date";
    var students
    = from s in db.Students
    select s;
    ViewBag.Filter
    = searchString;
    if (!string.IsNullOrEmpty(searchString))
    {
    students
    =students.Where(s => s.FirstMidName.ToUpper().Contains(searchString) || s.LastName.ToUpper().Contains(searchString));
    }
    switch (sortOrder)
    {
    case "Name desc":
    students
    = students.OrderByDescending(s => s.LastName);
    break;
    case "Date":
    students
    = students.OrderBy(s => s.EnrollmentDate);
    break;
    case "Date desc":
    students
    = students.OrderByDescending(s => s.EnrollmentDate);
    break;
    default:
    students
    = students.OrderBy(s => s.EnrollmentDate);
    break;
    }
    int pageSize = 2;
    int pageIndex = page ?? 1;
    return View(students.ToPagedList(pageIndex, pageSize));
    }

    要记得 pageIndex 从1开始  1表示第一页 

    只需简单的返回

      int pageSize = 2;
    int pageIndex = page ?? 1;
    return View(students.ToPagedList(pageIndex, pageSize));

    这样就OK了 就这么简单~~

    视图的model  改为    @model  PagedList<ContosoUniversity.Models.Student>

    然后分页的视图为

    <p>共有 @Model.TotalItemCount 条记录     @Model.CurrentPageIndex/@Model.TotalPageCount</p>

    @Html.Pager(Model, new PagerOptions { PageIndexParameterName = "page", ShowPageIndexBox = true, PageIndexBoxType = PageIndexBoxType.TextBox, PageIndexBoxWrapperFormatString = "请输入页数{0}" }, "Default", new { sortOrder = ViewBag.DateSortParm, searchString = ViewBag.Filter })

    看 一个要显示复杂的分页  就这么简单的完成了

    大家一定和我一样 关心生成的SQL语句怎么样 是否靠谱 效率可以么  让我们监控一下生成的SQL语句吧

    这是通过跟踪得到的SQL

    SELECT TOP (2) 
    [Extent1].[StudentID] AS [StudentID],
    [Extent1].[LastName] AS [LastName],
    [Extent1].[FirstMidName] AS [FirstMidName],
    [Extent1].[EnrollmentDate] AS [EnrollmentDate]
    FROM ( SELECT [Extent1].[StudentID] AS [StudentID], [Extent1].[LastName] AS [LastName], [Extent1].[FirstMidName] AS [FirstMidName], [Extent1].[EnrollmentDate] AS [EnrollmentDate], row_number() OVER (ORDER BY [Extent1].[EnrollmentDate] ASC) AS [row_number]
    FROM [dbo].[Student] AS [Extent1]
    )
    AS [Extent1]
    WHERE [Extent1].[row_number] > 2
    ORDER BY [Extent1].[EnrollmentDate] ASC
    利用 row_number() 实现的分页 ~~
    好了 分页OK了

    四.总结

    基本的EF操作OK了  合理利用第三方插件 大大提高了开发效率  学会借用 但也要知道原理

    EF做为ORM 框架 就是要处理关系  前面这几篇 都是简单的操作 没有设计关系

    下篇讲ORM的关系的处理  不仅是EF ORM框架都会遇到的 关系的处理 以及  多对多关系表里还需要其他字段时的处理

    转载 请保留连接~~


  • 相关阅读:
    json.dumps loads 终于区分出来了
    os.mkdir()和os.path.join()的区别
    readline与readlines之间的简单区别
    python:extend (扩展) 与 append (追加) 之间的天与地
    论raw_input与input之间的缠缠绵绵
    python-set
    HDU4343Interval query 倍增
    HDU2586How far away? LCA
    LCA算法解析-Tarjan&倍增&RMQ
    POJ1330Nearest Common Ancestors
  • 原文地址:https://www.cnblogs.com/wlflovenet/p/EFandMvc4.html
Copyright © 2011-2022 走看看