EF6 學習筆記(三):排序、過濾查詢及分頁


EF6 學習筆記索引目錄頁: ASP.NET MVC5 及 EF6 學習筆記 - (目錄整理)

上篇:EF6 學習筆記(二):操練 CRUD 增刪改查

本篇原文地址: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、修改Home\About 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 按鈕:

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM