【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 按鈕:

相關文章
相關標籤/搜索