來個目錄吧:
第一章-入門
第二章- Entity Framework Core Nuget包管理
第三章-創建、修改、刪除、查詢
第四章-排序、過濾、分頁、分組
第五章-遷移,EF Core 的codefirst使用
暫時就這么多。后面陸續更新吧
本次教程是完成排序、過濾、分頁和分組功能
在上一個教程中,學生實體的基本CRUD操作實現了一套網頁。在本教程中,您將向學生索引頁面添加排序,過濾和分頁功能。
您還將創建一個簡單分組的頁面。
下圖顯示了完成后頁面的外觀。用戶可以單擊列標題以按該列排序的鏈接。重復單擊列標題可在升序和降序之間切換。
給學生Index頁添加一個排序方法
打開SchoollController.cs 文件,將Index方法,替換為以下代碼:
public async Task<IActionResult> Index(string sortOrder)
{
ViewData["NameSortParm"] = String.IsNullOrEmpty(sortOrder) ? "name_desc" : "";
ViewData["DateSortParm"] = sortOrder == "Date" ? "date_desc" : "Date";
var students = from s in _context.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(await students.AsNoTracking().ToListAsync());
}
給index方法添加了個sortOrder參數,可以從Url接收值。查詢字符串的值由ASP.NET Core MVC的action方法的參數提供而來。
該參數會是一個字符串,“Name”或者“Date”,可以在后面添加下划線與"desc",指定為降序。默認排序為升序。
第一次加載Index頁面的時候,沒有查詢字符串。學生列表按照升序排序,這個是通過switch的默認值提供的。
當用戶點擊列標題超鏈接的時候,講標題的值賦予sortOrder參數。
ViewData 視圖使用兩個元素(NameSortParm和DateSortParm)來配置列標題超鏈接與對應的查詢字符串值。
public async Task<IActionResult> Index(string sortOrder)
{
ViewData["NameSortParm"] = String.IsNullOrEmpty(sortOrder) ? "name_desc" : "";//手動高亮
ViewData["DateSortParm"] = sortOrder == "Date" ? "date_desc" : "Date";//手動高亮
var students = from s in _context.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(await students.AsNoTracking().ToListAsync());
}
String.IsNullOrEmpty(sortOrder) ? "name_desc" : "";//手動高亮
這是一個三元運算符的語句。第一個指定如果sortOrder參數為null或為空,Name的排序應設置為“name_desc”; 否則,應將其設置為空字符串。這兩個語句使視圖可以按如下所示設置列標題超鏈接:
使用LINQ to Entities指定要排序的列。IQueryable在switch語句之前創建一個變量,在switch語句中進行排序,然后執行完畢后ToListAsync。
創建和修改IQueryable變量時,不會向數據庫發送任何查詢。
在IQueryable調用方法將對象轉換為集合之前,不會執行查詢ToListAsync。
將列標題排序添加到Index視圖中
替換Views / Students / Index.cshtml中的代碼,使用以下代碼添加列標題超鏈接。
@model IEnumerable<ContosoUniversity.Models.Student>
@{
ViewData["Title"] = "Index";
}
<h2>Index</h2>
<p>
<a asp-action="Create">Create New</a>
</p>
<table class="table">
<thead>
<tr>
<th>
<a asp-action="Index" asp-route-sortOrder="@ViewData["NameSortParm"]">@Html.DisplayNameFor(model => model.LastName)</a>
</th>
<th>
@Html.DisplayNameFor(model => model.FirstMidName)
</th>
<th>
<a asp-action="Index" asp-route-sortOrder="@ViewData["DateSortParm"]">@Html.DisplayNameFor(model => model.EnrollmentDate)</a>
</th>
<th></th>
</tr>
</thead>
<tbody>
@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>
<a asp-action="Edit" asp-route-id="@item.ID">Edit</a> |
<a asp-action="Details" asp-route-id="@item.ID">Details</a> |
<a asp-action="Delete" asp-route-id="@item.ID">Delete</a>
</td>
</tr>
}
</tbody>
</table>
此代碼使用屬性中的ViewData信息來使用適當的查詢字符串值設置超鏈接。
運行頁面,然后單擊"LastName"和"EnrollmentDate"列標題,以驗證排序是否有效。
給Student的Index視圖添加搜索功能
要向學生Index頁面添加過濾,您需要向視圖中添加一個文本框和一個提交按鈕,並對Index方法進行相應的更改。文本框將允許您輸入要在名字和姓氏字段中搜索的字符串。
向Index方法添加過濾功能
在StudentsController.cs中,將Index方法替換為以下代碼
public async Task<IActionResult> Index(string sortOrder, string searchString)
{
ViewData["NameSortParm"] = String.IsNullOrEmpty(sortOrder) ? "name_desc" : "";
ViewData["DateSortParm"] = sortOrder == "Date" ? "date_desc" : "Date";
ViewData["CurrentFilter"] = searchString;//手動高亮
var students = from s in _context.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(await students.AsNoTracking().ToListAsync());
}
您已向方法添加了searchString參數Index。searchString是從將添加到"Index”視圖的文本框中接收的。
您還在LINQ語句中添加了一個where子句,該代碼表示會搜索Student表中Last Name或者FirstMidName,如果有值則會返回到視圖頁面上。
注意:
這里你調用對象使用Where上的IQueryable方法,在運行的時候在服務器上處理。在某些情況下,您可能將該Where方法調用為內存中集合的擴展方法。
(例如,假設您更改使用_context.Students以便代替EF, DbSet引用返回集合的類型為IEnumerable。)結果通常是相同的,但在某些情況下可能不同。
例如,該Contains方法的.NET Framework實現默認情況下執行,是會區分大小寫的,但在SQL Server中,這是由SQL Server實例的排序規則設置決定的,默認為不區分大小寫
。你可以調用該ToUpper方法讓它顯式不區分大小寫: Where(s => s.LastName.ToUpper().Contains(searchString.ToUpper()).。
這將確保結果保持不變,如果你以后更改代碼使用一個存儲庫,
它返回一個IEnumerable集合而不是一個IQueryable對象(當你調用集合類型為IEnumerable的Contains方法,
你得到的.NET框架實現;當你在一個IQueryable對象上調用它,你得到數據庫提供實現。)
然而,這個解決方案存在性能損失。ToUpper代碼將在TSQL SELECT語句的WHERE子句中放置一個函數。
這將阻止優化程序使用索引。考慮到SQL大多數是安裝為不區分大小寫,最好避免ToUpper代碼,直到遷移到區分大小寫的數據存儲。
在學生Index視圖中添加一個搜索框
在Views/Student/Index.cshtml中,在table標簽之前添加突出顯示的代碼,以創建標題,文本框和搜索按鈕。
<p>
<a asp-action="Create">Create New</a>
</p>
<form asp-action="Index" method="get">
<div class="form-actions no-color">
<p>
Find by name: <input type="text" name="SearchString" value="@ViewData["currentFilter"]" />
<input type="submit" value="Search" class="btn btn-default" /> |
<a asp-action="Index">Back to Full List</a>
</p>
</div>
</form>
<table class="table">
此代碼使用