1. 程式人生 > >MVC5 Entity Framework學習之新增排序、篩選和分頁功能

MVC5 Entity Framework學習之新增排序、篩選和分頁功能

前一篇文章中實現了對Student 實體的的基本CRUD操作,在這篇文章中將演示如何為Students Index頁面新增排序、篩選和分頁的功能。

下面是當完成排序、篩選和分頁功能後的截圖,你可以點選列標題來進行排序。


1.為 Students Index頁面新增列排序連結

要為Students Index頁面新增排序功能,你需要修改Student controller的Index方法,併為Student Index檢視新增程式碼。

向Index方法新增排序功能

開啟Controllers\StudentController.cs,使用下面的程式碼替換Index 方法

public ActionResult 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.LastName);
         break;
   }
   return View(students.ToList());
}

上面的程式碼接收URL中的查詢字串作為sortOrder引數,該引數是"Name"或"Date",使用三元運算子判斷並加下劃線和"desc"來指名這是一個降序排序,預設是按升序排序。

第一次訪問Index頁面時是沒有查詢字串的,students按照LastName作升序排序顯示,這是由switch語句中的default指定的。當用戶點選某列的標題連結時,URL的查詢字串中就含有了相應的sortOrder值。

這裡使用了兩個ViewBag變數以便檢視可以將合適的查詢字串提供給列標題連結。

ViewBag.NameSortParm = String.IsNullOrEmpty(sortOrder) ? "name_desc" : "";
ViewBag.DateSortParm = sortOrder == "Date" ? "date_desc" : "Date";

這裡使用了三元運算子,上面第一個指明假如sortOrder引數為null或為空,則ViewBag.NameSortParm被賦值為"name_desc",否則將其賦值為空。其排序規則為:

Current sort order Last Name Hyperlink Date Hyperlink
Last Name ascending descending ascending
Last Name descending ascending ascending
Date ascending ascending descending
Date descending ascending ascending
該方法使用LINQ to Entities來指明要排序的列,上面的程式碼在switch語句前新建了一個 IQueryable變數,然後在switch中修改它,最後在switch語句後呼叫ToList方法。當你建立並修改IQueryable變數時,並沒有向資料庫傳送查詢命令,直到呼叫ToList方法將IQueryable 物件轉換為一個集合時才真正的執行查詢命令。因此,直到return View語句,才會執行查詢語句。

作為另一種為每一個排序編寫不同的LINQ語句的替代方法,可以使用動態建立LINQ句。

為Student Index檢視新增列標題連結


開啟Views\Student\Index.cshtml,新增下面的程式碼
<p>
    @Html.ActionLink("Create New", "Create")
</p>
<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) {

上面的程式碼使用ViewBag屬性使用相應的查詢字串來設定列標題連結的值。

執行專案,點選Last Name和Enrollment Date行標題,驗證排序功能



點選Last Name標題,students 將按降序排列


2.向Students Index頁面新增搜尋框

要在Students Index頁面中新增搜尋功能,你需要在檢視中新增一個文字框和一個提交按鈕並修改Index方法,通過在文字框中輸入 first name或者last name 來搜尋相應的Students資料。

在Index方法中新增篩選功能

開啟Controllers\StudentController.cs,使用下面的程式碼替換Index方法

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());
}

上面的程式碼將searchString引數新增到Index方法,你也可以向LINQ語句中新增where子句來查詢那些first name 或者 last name中包含查詢條件的student。查詢條件就是你所填寫在Index檢視的文字框中的字串,只有當文字框中由查詢條件時,where語句才會執行。

注意:在很多情況下,你可以呼叫無論該是Entity Framework實體集中的方法還是位於記憶體集合中的作為擴充套件的方法,得到的結果通常是一樣的,但是有些情況下可能不同。

舉例來說,.NET Framework實現了Contains方法,當你向該方法傳遞一個空字串作為引數時,它將返回所有行,但是在SQL Server Compact 4.0的  Entity Framework提供程式中不反回任何行,因此上面的程式碼(將where語句放在if語句中)可以確保所有SQL Server版本都能返回相同的結果。另外,.NET Framework實現的Contains方法預設是大小寫敏感的,但是Entity Framework SQL Server 提供程式執行的比較是不區分大小寫的。因此,此處呼叫ToUpper方法來明確這裡執行不區分大小寫的比較,這樣當接下來使用倉儲模式時不需要修改程式碼就可以得到相同的結果(IEnumerable集合中的Contains方法是由 .NET Framework實現的,IQueryable物件中的Contains方法是由資料庫提供程式實現的)。

對於不同的資料庫提供程式或者使用IQueryable物件作比較或者使用IEnumerable集合作比較時,Null值得處理也是不同的。例如某些情況下,where條件比如table.Column !=0可能不返回那些包含null值得列,

在Student Index 檢視中新增一個搜尋框


開啟Views\Student\Index.cshtml,新增如下程式碼
<p>
    @Html.ActionLink("Create New", "Create")
</p>

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

<table>
    <tr>

執行專案,輸入要搜尋的值,點選Search驗證搜尋功能是否正常


注意在URL中並不包含搜尋字串,這意味著如果你將此頁面加入書籤,然後通過書籤來開啟此頁面,你將無法得到篩選後的結果。

在Students Index頁面中新增分頁功能

要向Students Index頁面中新增分頁,你需要安裝PagedList.Mvc NuGet包,然後你可以在Index 方法中做一些修改並在Index檢視中新增分頁連結。PagedList.Mvc是ASP.NET MVC中眾多分頁和排序包中比較好的一個,這裡只是使用它來作為演示,並非作為推薦選擇。

安裝PagedList.Mvc NuGet包

PagedList包作為PagedList.Mvc包的依賴項會自動安裝到專案中,PagedList包為IQueryable和IEnumable集合添加了PagedList集合型別和擴充套件方法。PagedList擴充套件方法為從IQueryabl或IEnumable集合產生的PagedList集合資料建立了一個單一的頁面,並且PagedList集合提供了多個便於分頁的屬性和方法。PagedList.Mvc包中含有分頁幫助器並可在頁面中顯示分頁按鈕。

依次開啟Tools-> Library Package Manager-> Package Manager Console

在開啟的Package Manager Console中確保Package source是nuget.org 並且Default project是 ContosoUniversity,最後輸入Install-Package PagedList.Mvc命令


在Index方法中新增分頁功能

開啟Controllers\StudentController.cs,新增PagedList名稱空間

using PagedList;

使用下面的程式碼替換Index方法
public ViewResult Index(string sortOrder, string currentFilter, string searchString, int? page)
{
   ViewBag.CurrentSort = sortOrder;
   ViewBag.NameSortParm = String.IsNullOrEmpty(sortOrder) ? "name_desc" : "";
   ViewBag.DateSortParm = sortOrder == "Date" ? "date_desc" : "Date";

   if (searchString != null)
   {
      page = 1;
   }
   else
   {
      searchString = currentFilter;
   }

   ViewBag.CurrentFilter = searchString;

   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:  // Name ascending 
         students = students.OrderBy(s => s.LastName);
         break;
   }

   int pageSize = 3;
   int pageNumber = (page ?? 1);
   return View(students.ToPagedList(pageNumber, pageSize));
}
上面的程式碼添加了一個page引數,一個當前排序順序引數,一個當前搜尋條件引數
public ActionResult Index(string sortOrder, string currentFilter, string searchString, int? page)

頁面第一次顯示或者使用者還沒有點選分頁或排序連結,所有引數值都為null。如果點選分頁連結,page變數將包含要顯示的頁碼。

ViewBag屬性向檢視提供了當前的排序順序,因為在點選分頁連結後必須要保持當前的排序順序。

ViewBag.CurrentSort = sortOrder;
另一個屬性ViewBag.CurrentFiler向檢視提供當前的搜尋條件,該值必須要被包含在分頁連結中以保證是針對搜尋結果進行分頁,同時在頁面重新顯示時,搜尋字串必須顯示在搜尋框中。如果在分頁時修改了搜尋字串,頁碼必須要被重置為1,因為新的搜尋條件可導致不同的搜尋結果。當向搜尋框輸入搜尋字串並點選提交按鈕,這是searchString的值不為null。
if (searchString != null)
{
    page = 1;
}
else
{
    searchString = currentFilter;
}
在該方法的結尾部分,學生IQueryable物件的ToPagedList擴充套件方法將學生查詢轉換為一個支援分頁的學生集合型別,並將該學生集合傳遞給檢視
int pageSize = 3;
int pageNumber = (page ?? 1);
return View(students.ToPagedList(pageNumber, pageSize));

ToPagedList方法需要一個頁碼引數,兩個問號表示空合併操作符(null-coalescing operator),空合併操作符為nullable 型別指定預設值,表示式(page ?? 1)表示如果page值不為空就返回該值,否則返回1。

向 Student Index檢視新增分頁連結

開啟Views\Student\Index.cshtml,使用下面的程式碼替換

@model PagedList.IPagedList<ContosoUniversity.Models.Student>
@using PagedList.Mvc;
<link href="~/Content/PagedList.css" rel="stylesheet" type="text/css" />

@{
    ViewBag.Title = "Students";
}

<h2>Students</h2>

<p>
    @Html.ActionLink("Create New", "Create")
</p>
@using (Html.BeginForm("Index", "Student", FormMethod.Get))
{
    <p>
        Find by name: @Html.TextBox("SearchString", ViewBag.CurrentFilter as string)
        <input type="submit" value="Search" />
    </p>
}
<table class="table">
    <tr>
        <th>
            @Html.ActionLink("Last Name", "Index", new { sortOrder = ViewBag.NameSortParm, currentFilter=ViewBag.CurrentFilter })
        </th>
        <th>
            First Name
        </th>
        <th>
            @Html.ActionLink("Enrollment Date", "Index", new { sortOrder = ViewBag.DateSortParm, currentFilter=ViewBag.CurrentFilter })
        </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>
<br />
Page @(Model.PageCount < Model.PageNumber ? 0 : Model.PageNumber) of @Model.PageCount

@Html.PagedListPager(Model, page => Url.Action("Index", 
    new { page, sortOrder = ViewBag.CurrentSort, currentFilter = ViewBag.CurrentFilter }))

頁面頂部的@model語句指明檢視現在獲取的是PagedList物件而不是List物件。

using PagedList.Mvc語句可以使MVC幫助器提供分頁按鈕。

在程式碼中使用了 BeginForm 的過載方法並添加了FormMethod.Get 引數。

@using (Html.BeginForm("Index", "Student", FormMethod.Get))
{
    <p>
        Find by name: @Html.TextBox("SearchString", ViewBag.CurrentFilter as string)  
        <input type="submit" value="Search" />
    </p>
} 

預設情況下BeginForm 使用POST方式提交表單資料,這意味著引數通過HTTP訊息正文傳遞而不是通過URL查詢字串。當你指定使用HTTP GET時,表單資料通過URL查詢字串來傳遞,這樣可以允許使用者將URL儲存為書籤。W3C guidelines for the use of HTTP GET推薦你應該在不會更新資料的方法中使用GET方式。

搜尋框使用當前的搜尋字串進行初始化,以便在分頁的時候不會丟失搜尋字串。

Find by name: @Html.TextBox("SearchString", ViewBag.CurrentFilter as string)  
列標題連結使用了搜尋字串並將其傳遞給控制器以便使用者可以對搜尋結果進行排序。
@Html.ActionLink("Last Name", "Index", new { sortOrder=ViewBag.NameSortParm, currentFilter=ViewBag.CurrentFilter })

顯示當前頁碼和總頁數

Page @(Model.PageCount < Model.PageNumber ? 0 : Model.PageNumber) of @Model.PageCount

如果沒有要顯示的頁,就顯示"Page 0 of 0"

PagedListPager幫助器顯示分頁按鈕

@Html.PagedListPager( Model, page => Url.Action("Index", new { page }) )
PagedListPager幫助器提供了多個選項,你可以自定義URL和樣式

執行專案


使用不同的排序方式,並點選分頁按鈕跳轉至不同的頁碼,確保分頁功能正常,然後輸入查詢條件,再次驗證分頁和搜尋功能正常。


3.建立顯示學生統計資訊的About頁面

要讓About頁面顯示在每一個入學日共有多少學生登記,需要將學生分組並進行簡單的計算,要做到這些,需要執行下列操作:

  • 需要為要傳遞給檢視的資料建立一個檢視模型類
  • 修改Home控制器中的About方法
  • 修改About檢視

建立檢視模型

建立一個ViewModels資料夾並新增名為EnrollmentDataGroup.cs的類,使用下面的程式碼替換
using System;
using System.ComponentModel.DataAnnotations;

namespace ContosoUniversity.ViewModels
{
    public class EnrollmentDateGroup
    {
        [DataType(DataType.Date)]
        public DateTime? EnrollmentDate { get; set; }

        public int StudentCount { get; set; }
    }
}

修改Home控制器

開啟HomeController.cs,在檔案頂部新增using語句引入名稱空間

using ContosoUniversity.DAL;
using ContosoUniversity.ViewModels;
為資料庫上下文新增類變數
public class HomeController : Controller
{
    private SchoolContext db = new SchoolContext();
使用下面的程式碼替換About方法
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());
}

使用LINQ語句對Student實體按照enrollment date分組,計算每個分組的實體數量,並將結果儲存在EnrollmentDateGroup檢視模型物件的集合中。

新增Dispose方法

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

修改About檢視

開啟Views\Home\About.cshtml ,使用下面的程式碼替換

@model IEnumerable<ContosoUniversity.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>

執行專案,點選About連結,顯示學生統計資訊

還大家一個健康的網路環境,從你我做起

THE END

相關推薦

MVC5 Entity Framework學習新增排序篩選功能

前一篇文章中實現了對Student 實體的的基本CRUD操作,在這篇文章中將演示如何為Students Index頁面新增排序、篩選和分頁的功能。 下面是當完成排序、篩選和分頁功能後的截圖,你可以點選列標題來進行排序。 1.為 Students Index頁面新增列排序連

排序 篩選與 ASP.NET MVC 應用程式中的實體框架

http://www.asp.net/mvc/overview/getting-started/getting-started-with-ef-using-mvc/sorting-filtering-and-paging-with-the-entity-frame

MVC5 Entity Framework學習實現主要的CRUD功能

之前 顯式 sea variable host ive spl url 轉載 在上一篇文章中,我們使用Entity Framework 和SQL Server LocalDB創建了一個MVC應用程序,並使用它來存儲和顯示數據。在這篇文章中,你將對由 MVC框架自己主

MVC5 Entity Framework學習實現繼承

之前你已經學習瞭如何處理併發異常,在本節中你將學習如何實現繼承。 在面向物件的程式設計中,你可以使用繼承來重用程式碼。接下來你將修改Instructor和Student類,讓它們派生自Person基類,該基類包含instructor和student共有的屬性如LastNam

MVC5 Entity Framework學習實現基本的CRUD功能

在上一篇文章中,我們使用Entity Framework 和SQL Server LocalDB建立了一個MVC應用程式,並使用它來儲存和顯示資料。在這篇文章中,你將對由 MVC框架自動建立的CRUD(create, read, update, delete)程式碼進行修改

Koa2學習旅----結合 jqPaginator實現列表

1.下載jqPaginator.js  放在靜態目錄裡面 2、在需要分頁的地方引入jqPaginator.js  3、在需要分頁的地方加個空div     <div id="page" class="pagination"></

DAY105 - 路飛學城(二)- 路飛學城emement-ui課程列表,課程詳情

一、emement-ui 1.下載 npm install element-ui 2.使用 # main.js中配置 import ElementUI from 'element-ui'; import 'element-ui/lib/theme-chalk/index.css'; Vue.use(E

MVC學習小結[數據綁定]

string類 ring desc 寫上 etl 三個參數 跳轉 失效 循環 一、項目搭建完成後,在控制器裏邊寫入方法:例如 public ActionResult Index(){ var model=new Product(){id=1,name="產品

CookieSession

為什麼使用Cookie:因為HTTP請求是沒有狀態的,每一次請求都是獨立的。 什麼是Cookie:Cookie就是儲存在瀏覽器上的鍵值對,服務端控制著響應,在響應裡新增一個鍵值對,讓瀏覽器在本地儲存,下一次請求的時候,自動攜帶這個鍵值對,是在瀏覽器端設定的,瀏覽器端也可以禁用Cookie。 Cookie的

Entity Framework多檢視條件查詢排序

      Entity Framework在C#中常常用於底層和資料庫互動,也就是DAL層。而Entity Framework中與資料庫互動時底層與資料庫通訊的重要的容器就是DbContext。     而使用DbContext對資料庫聯表查詢是最常見的操作。這裡介紹多檢

.NET Core學習筆記(8)——Entity Framework CoreDatabase First

曾經我以為再也不會去弄啥Database First,然鵝我錯了。這個世界上就是有啪啪打臉和真香的時候。當小夥伴拿著做好的DB表結構和SQL指令碼遞過來的時候,我知道我沒法拒絕。望著他突起的肱二頭肌和充滿殺意的臉龐,我怎能忍心說,來來來,我們Code First一把……DB Fir

.NET Core學習筆記(9)——Entity Framework CoreCode First

上篇我們介紹了怎麼通過已有的SQLServer表來建立實體類,本篇我們改用Code First的方式,由C#程式碼書寫的實體類來生成SQLServer表。並且通過簡單的Console APP往SQLServer表寫入資料。首先我們先建立3個空的Projects,其中EfCodeFirst是作為啟動項的Cons

.NET 5學習筆記(10)——Entity Framework Core切換SQLServerSQLite

上一篇我們梳理了CodeFist的一般流程,本篇我們討論如何在一套程式碼中,支援SQL Server和SQLite的切換。同時從本篇開始,我們從.NET Core 3.1 遷移到.NET 5。相信.NET 到了5這個版本,所有人都不會再懷疑某軟跨平臺的決心。而且SQL Server也從2017版本開始支援Li

Python小白學習路—whilefor循環運算

範圍 src 格式 次循環 pen 映射 年齡 退出 finish Python裏面的循環跟其他語言裏的循環基本一致,只是書寫格式不同。 1.for循環: for [循環條件]:[循環語句]  滿足循環條件,則執行循環語句,執行一次判斷一次,不滿足則結束循環。 簡單的循環:

Entity Framework學習筆記——EF簡介(一篇文章告訴你什麽是EF)

比較 編程 ast 定義 .aspx b2c 文件創建 發送 ase Entity Framework是以ADO.NET為基礎,面向數據的“實體框架”。以下簡稱EF。 它利用了抽象化數據結構的方式,將每個數據庫對象都轉換成應用程序對象 (entity),

Entity Framework學習筆記——edmx文件

tinc metadata glob 兩個類 color empty 完成 文件中 文件的 上文簡單介紹了一下Entity FrameWork,這裏說一下EF的核心——edmx文件。 在VisualStudio中建立edmx文件(此例環境為Visual

大數據學習九——Combiner,Partitioner,shuffleMapReduce排序分組

pareto 聚合 文件 ner 數據傳輸 定義排序 str ack 獲取數據 1.Combiner Combiner是MapReduce的一種優化手段。每一個map都可能會產生大量的本地輸出,Combiner的作用就是對map端的輸出先做一次合並,以減少map和reduc

ASP.NET CORE系列【六】Entity Framework Core 數據庫遷移

snapshot 文章 src AD data 上下 ont pre 發生 前言 最近打算用.NET Core寫一份簡單的後臺系統,來練練手 然後又用到了Entity Framework Core 發現園子裏有些文章講得不是那麽細節,對於新手小白來說,可能會有點懵。 特意

JVM基礎學習基本概念可見性與同步

讀寫 應用 資源 而不是 檢查 依靠 完成 層次 並發 開發高性能並發應用不是一件容易的事情。這類應用的例子包括高性能Web服務器、遊戲服務器和搜索引擎爬蟲等。這樣的應用可能需要同時處理成千上萬個請求。對於這樣的應用,一般采用多線程或事件驅動的 架構 。對於Java來說,在

常用算法----選擇排序插入排序希爾排序

插入 @override == 撰寫 [] 步長 1.5 shells 撲克 一些說明 我將會寫一系列關於算法的博客,因為我是程序員,並不是計算機科學家,也即我是搞工程的,並不是搞學術的,所以對於我來說,最重要的就是 1.有哪些算法 2.這些算法的原理 3.這些