来个目录吧:
第一章-入门
第二章- 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">
此代码使用