【EF6学习笔记】(三)排序、过滤查询及分页

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

说明:学习笔记参考原文中的流程,为了增长实际操做性,并可以深刻理解,部分地方根据实际状况作了一些调整;而且根据本身的理解作了一些扩展。git

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

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

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

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 的列头部分,修改成如下代码:mvc

复制代码
<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的时候,把参数改成正序,这样就能够实现点一次变换正反序的想法。app

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

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

先在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步:

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

二、修改Home\About Action;

三、修改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 按钮:

相关文章
相关标签/搜索