zoukankan      html  css  js  c++  java
  • 【EF6学习笔记】(三)排序、过滤查询及分页

    本篇原文地址:Sorting, Filtering, and Paging

    说明:学习笔记参考原文中的流程,为了增加实际操作性,并能够深入理解,部分地方根据实际情况做了一些调整;并且根据自己的理解做了一些扩展。

    本人的学习环境: VS2017 + EF 6.1.3 + .NET 4.6.1

    上一篇完成基本的CRUD操作;本篇学习如何进行排序显示、过滤查询及分页显示;

    Step1 排序显示,主要是对Student列表页面进行点击表列头进行该列排序;点击一次从正序变为反序,再点击一次从反序变为正序;

    Student 控制器 Index Action 代码改为: (目前先只考虑了LastName和EnrollmentDate的排序 ) 

    复制代码
            public ActionResult Index(string sortOrder)
            {
           //如果sortOrder为空,则把name_desc值传到view保存,下一次点击列头进行请求的时候,就会带回这个值,表示下一次用 Desc 倒序方式;
    ViewBag.NameSortParm
    = String.IsNullOrEmpty(sortOrder) ? "name_desc" : "";
           //同理如果sortOrder为Date,则把date_desc值传到view保存,下一次点击列头进行请求时,带回这个值,表示下一次用 Date 倒序方式; 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.LastName); break; } return View(students.ToList()); }
    复制代码

    对于View 的列头部分,修改为以下代码:

    复制代码
        <tr>
            <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>
            <th></th>
        </tr>
    复制代码

    排序操作主要是巧妙的利用ViewBag里设置一个Sort值来进行来回请求的时候进行开关切换,传进来是正序的ViewBag参数,则返回View的时候,把ViewBag参数改为倒序,这样下次请求的时候,参数就是倒序的ViewBag参数,再在返回View的时候,把参数改为正序,这样就可以实现点一次变换正反序的想法。

    然后再利用EF先查询出所有学生记录,再利用OrderBy 或者 OrderByDescending来进行数据排序,最后把排序结果返回给View去显示;

    Step2 检索过滤,这个相对比较简单,主要是利用EF查询的时候通过where加Lamda表达式来筛选出符合条件的数据。

    先在View中增加一个过滤检索条件的输入框:(就增加在Create的<p>和主Table之间)

    复制代码
    @using (Html.BeginForm())
    {
        <p>
            Find by name: @Html.TextBox("SearchString") 
            <input type="submit" value="Search" />
    </p>
    }
    复制代码

    Index Action中增加过滤操作:

    复制代码
            public ActionResult 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.Contains(searchString)
                                           || s.FirstMidName.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.LastName);
                        break;
                }
                return View(students.ToList());
            }
    复制代码

    //后续增加一些思考

    Step3 分页显示

    原文采用PagedList.Mvc 而PagedList的github页面显示 PagedList已经不再维护升级,建议使用X.PagedList替代;

    注:要用X.PagedList.Mvc的话,.net 必须4.5.2以上版本才可以;

    下面用X.PagedList.Mvc来完成后续分页测试;

    先通过NuGet安装: Install-Package X.PagedList.Mvc

    (现在NuGet经常无法直接安装。。。头疼)

    Student 控制器先增加申明: using X.PagedList;

    Index Action 代码修改为:

    复制代码
            public ActionResult Index(string sortOrder, string searchString, int? page)
            {
                //如果sortOrder为空,则把name_desc值传到view保存,下一次点击列头进行请求的时候,就会带回这个值,表示下一次用 Desc 倒序方式;
                ViewBag.NameSortParm = String.IsNullOrEmpty(sortOrder) ? "name_desc" : "";
                //同理如果sortOrder为Date,则把date_desc值传到view保存,下一次点击列头进行请求时,带回这个值,表示下一次用 Date 倒序方式;
                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.Contains(searchString)
                                           || s.FirstMidName.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.LastName);
                        break;
                }
    
                var pageNumber = page ?? 1;
            //简单固定数量分页,每页3条记录,如果要动态数量,需要修改 var onePageOfStudents = students.ToPagedList(pageNumber, 3); return
    View(onePageOfStudents); }
    复制代码

     View变更为:

    复制代码
    @model IEnumerable<EFTest.Models.Student>
    
    @{
        ViewBag.Title = "Index";
    }
    
    @using X.PagedList.Mvc;
    @using X.PagedList;
    
    <h2>Index</h2>
    
    <p>
        @Html.ActionLink("Create New", "Create")
    </p>
    
    @using (Html.BeginForm())
    {
        <p>
            Find by name: @Html.TextBox("SearchString")
            <input type="submit" value="Search" />
        </p>
    }
    
    <table class="table">    
        <tr>
            <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>
            <th></th>
        </tr>
    @foreach (var item in Model) {
        <tr>
            <td>
                @Html.DisplayFor(modelItem => item.LastName)
            </td>
            <td>
                @Html.DisplayFor(modelItem => item.FirstMidName)
            </td>
            <td>
                @Html.DisplayFor(modelItem => item.EnrollmentDate)
            </td>
            <td>
                @Html.ActionLink("Edit", "Edit", new { id=item.ID }) |
                @Html.ActionLink("Details", "Details", new { id=item.ID }) |
                @Html.ActionLink("Delete", "Delete", new { id=item.ID })
            </td>
        </tr>
    }
    </table>
    @Html.PagedListPager((IPagedList)Model, page => Url.Action("Index", new { page }))
    复制代码

    实现效果:

    X.PagedList.Mvc 比原来的PagedList.Mvc简单不少;

    (CSS样式是Twitter Bootstrap 样式的,也可以根据自己要求自定义,在Package里也有PagedList.css可以用

    以前写的所谓这种方式是假分页的话是错的,收回。

    通过下一章的命令拦截调试,可以看到执行的SQL语句,理论上应该是服务器端真分页,SQL语句只执行取总行数以及当前请求页的数据:

    最后做一个Student的统计页面:

    主要3步:

    1、新建一个ViewModel用于显示统计数据;

    2、修改HomeAbout Action;

    3、修改About 对应的视图

    复制代码
    using System;
    using System.ComponentModel.DataAnnotations;
    
    namespace EFTest.ViewModels
    {
        public class EnrollmentDateGroup
        {
            [DataType(DataType.Date)]
            public DateTime? EnrollmentDate { get; set; }
    
            public int StudentCount { get; set; }
        }
    }
    复制代码

    Home 控制器加入以下申明:

    using EFTest.DAL;
    using EFTest.ViewModels;

    Home 控制器加入上下文私有属性:

    private SchoolContext db = new SchoolContext();

    Home 控制器加入About Action :

    复制代码
    public ActionResult About()
    {
        IQueryable<EnrollmentDateGroup> data = from student in db.Students
                   group student by student.EnrollmentDate into dateGroup
                   select new EnrollmentDateGroup()
                   {
                       EnrollmentDate = dateGroup.Key,
                       StudentCount = dateGroup.Count()
                   };
        return View(data.ToList());
    }
    复制代码

    最后再加入关闭数据库连接代码:

    protected override void Dispose(bool disposing)
    {
        db.Dispose();
        base.Dispose(disposing);
    }

    为About Action新建一个空视图,然后用以下代码替换:

    复制代码
    @model IEnumerable<EFTest.ViewModels.EnrollmentDateGroup>
               
    @{
        ViewBag.Title = "Student Body Statistics";
    }
    
    <h2>Student Body Statistics</h2>
    
    <table>
        <tr>
            <th>
                Enrollment Date
            </th>
            <th>
                Students
            </th>
        </tr>
    
    @foreach (var item in Model) {
        <tr>
            <td>
                @Html.DisplayFor(modelItem => item.EnrollmentDate)
            </td>
            <td>
                @item.StudentCount
            </td>
        </tr>
    }
    </table>
    复制代码

    最后运行起来看下效果,点击Home 页 About 按钮:

  • 相关阅读:
    JQuery 练习题解析
    php 分页
    php批量删除
    PHP 多条件查询之简单租房系统
    php MySQLi数据库操作 封装类
    PHP MySQLi 增删改查
    jquery Deferred使用经验
    http2.0笔记
    window.name 跨域
    浏览器缓存读取机制大解底
  • 原文地址:https://www.cnblogs.com/wyt007/p/8488794.html
Copyright © 2011-2022 走看看