博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
EF6与mvc5系列(3):在MVC应用程序中使用EF进行排序,过滤和分页
阅读量:4356 次
发布时间:2019-06-07

本文共 10737 字,大约阅读时间需要 35 分钟。

上节中,我们实现了基本增删查改功能,本节中要在Student的Index页面添加排序,分页和过滤功能,同时创建一个简单的分组页面。

在Student的Index页面添加列排序链接

为了在Index页面中实现排序。修改Index方法中的代码。

在Index方法中添加排序功能

修改Student控制器中的Index方法,在Index视图中添加代码。

// GET: /Student/        public ActionResult Index(string sortOrder)        {            ViewBag.NameSort = string.IsNullOrEmpty(sortOrder) ? "name_desc" : "";            ViewBag.DateSort=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查询字符串参数,查询字符串的值是由MVC提供,作为一个参数传递给action。参数值是“Name”或者“Date”,然后后面随意跟随_desc用于说明降序排列,默认是正序。

第一次请求Index页面,是没有查询字符串的,页面会呈现出按照Last字段正序查询出的数据。当用户点击列标题超链接的时候,会传递sortOrder的值进行查询。

Index方法使用了 指定要排序的列。在switch语句之前创建 变量,并在switch语句中修改其值,最后调用ToList()方法。当你创建并修改IQueryable变量的时候,不向数据库中发送查询请求。当你将IQueryable对象通过像ToList这样的方法,转换为集合的时候才会执行查询。有关更多动态LINQ,请查看:.

在Index视图页添加列标题超链接

对Index视图代码做如下修改:

@Html.ActionLink("LastName", "Index", new { sortOrder=ViewBag.NameSort}) @*@Html.DisplayNameFor(model => model.FirstMidName)*@ FirstMidName @Html.ActionLink("Enrollment Date", "Index", new { sortOrder=ViewBag.DateSort})

在Index页面添加搜索框

接下来实现页面的搜索功能

在Index方法中添加过滤功能

修改Index方法如下:

// GET: /Student/        public ActionResult Index(string sortOrder,string searchStr)        {            ViewBag.NameSort = string.IsNullOrEmpty(sortOrder) ? "name_desc" : "";            ViewBag.DateSort=sortOrder=="Date"?"date_desc":"Date";            var students = from s in db.Students select s;            if (!string.IsNullOrEmpty(searchStr))            {                students = students.Where(s=>s.LastName.Contains(searchStr)||s.FirstMidName.Contains(searchStr));            }            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());        }

在Index方法中添加searchStr参数,此参数来自页面的输入框中写入的值,在where字句中添加LINQ筛选出符合条件的实体。

注意:在很多情况下,可以对EF实体集,或者作为内存中集合的扩展方法调用相同的方法,其作用结果相同。但是有些情况下是不同的。

例如:.NET Framework实现Contains方法的时候,如果传入空字符串会返回数据库中所有行。但是对于SQL Server Compact 4实体框架提供程序,如果输入空字符串不会返回任何行。因此才会将上述中的where字句放在if中以确保不同情况下都能显示数据。同时,.NET Framework实现Contains方法的时候默认是区分大小写的。但是SQL Server Compact 4实体框架提供程序默认不区分大小写。为了避免这种情况,我们可以使用ToUpper方法避免这种情况。稍后的代码中,我们的结果集会返回一个IEnumerable集合,而不是一个IQueryable对象。对IEnumerable集合调用Contains方法的时候,是由.NET Framework实现。而对IQueryable调用Contains方法的时候,是由数据库提供程序实现的。

不同的数据库应用程序对NULL处理也不同。例如,有时候一个where中包含table.Column != 0时,不会返回带有NULL的数据行。更多信息请查看:.

Index视图中添加搜索框

如下:

@Html.ActionLink("Create New", "Create")

@using(Html.BeginForm()){

Find by Name:@Html.TextBox("searchStr")

}

注意:.NET Framework实现了Contains方法,当你传入的字符串为空时,返回所有行,但是SQL Server契约4.0的EF提供程序对于这种情况会返回0行数据。就是考虑到这种情况所以将where声明放在If中。.NET Framework对于Contains方法是区分大小写的,但是EF sql server提供程序对于Contains方法是不区分大小写的。对于IEnumerable

集合调用Contains方法会由.NET Framework实现。当对IQueryable对象调用Contains方法,会由数据库提供程序实现。

空处理对于不同的数据库提供程序或者 IQueryable对象和IEnumerable集合也是不同的。详情查看: .

添加分页

接下来在Index页面添加分页,我们使用PagedList.Mvc进行分页。我们仅仅在这个例子中使用它,不推荐在其他地方使用其进行分页。

安装PagedList.MVC NuGet包。

工具->库程序包管理器(NuGet程序包管理器)—>程序包管理器控制台->Install-Package PagedList.Mvc

生成项目

在Index方法中添加分页

引入命名空间

using PagedList;
public ActionResult Index(string sortOrder,string searchStr,int? page,string currentFilter)        {            ViewBag.CurrentSort = sortOrder;            //如果是sortOrder为空,返回name_desc,否则返回空字符串。            ViewBag.NameSort = string.IsNullOrEmpty(sortOrder) ? "name_desc" : "";            ViewBag.DateSort=sortOrder=="Date"?"date_desc":"Date";            if (searchStr!=null)            {                page = 1;            }            else            {                searchStr = currentFilter;            }            ViewBag.CurrentFilter = searchStr;            var students = from s in db.Students select s;            if (!string.IsNullOrEmpty(searchStr))            {                students = students.Where(s=>s.LastName.Contains(searchStr)||s.FirstMidName.Contains(searchStr));            }            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;            }            int pageSize = 2;            int pageNum = (page ?? 1);            return View(students.ToPagedList(pageNum,pageSize));        }
1 @*@model IEnumerable
*@ 2 @model PagedList.IPagedList
3 @using PagedList.Mvc 4 5 6 @{ 7 ViewBag.Title = "Student"; 8 } 9 10

Student

11 12

13 @Html.ActionLink("Create New", "Create")14

15 @using(Html.BeginForm("Index","Student",FormMethod.Get))16 {17

18 Find by Name:@Html.TextBox("searchStr", ViewBag.CurrentFilter as string)19 20

21 }22
23
24
27
31
34
35
36 37 @foreach (var item in Model) {38
39
42
45
48
53
54 }55 56
25 @Html.ActionLink("LastName", "Index", new { sortOrder = ViewBag.NameSort, currentFilter = ViewBag.CurrentFilter })26 28 @*@Html.DisplayNameFor(model => model.FirstMidName)*@29 FirstMidName30 32 @Html.ActionLink("Enrollment Date", "Index", new { sortOrder = ViewBag.DateSort, currentFilter = ViewBag.CurrentFilter })33
40 @Html.DisplayFor(modelItem => item.LastName)41 43 @Html.DisplayFor(modelItem => item.FirstMidName)44 46 @Html.DisplayFor(modelItem => item.EnrollmentDate)47 49 @Html.ActionLink("Edit", "Edit", new { id=item.ID }) |50 @Html.ActionLink("Details", "Details", new { id=item.ID }) |51 @Html.ActionLink("Delete", "Delete", new { id=item.ID })52
57
58 第 @(Model.PageCount
Url.Action("Index", new { page, sortOrder = ViewBag.CurrentSort, currentFilter = ViewBag.CurrentFilter }))

页面首次加载或者用户未点击分页或者分类链接,所有的参数为null,如果点击分页链接,将看到page变量中包含了页码。

ViewBag属性提供给页面一个当前排序,因为分页时也要保持现有的排序,

ViewBag.CurrentSort = sortOrder;

另一个属性ViewBag.CurrentFilter,向页面提供当前过滤字符串,这样确保分页的时候也保持当前过滤条件。如果分页时查找条件改变,页面就重置为1,因为新的过滤条件查询结果与之前不同。

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

在方法的最后,students的IQueryable扩展方法:ToPagedList,将查询结果转为一个分页的学生集合,并传递到视图页。

int pageSize = 3;int pageNumber = (page ?? 1);return View(students.ToPagedList(pageNumber, pageSize));

修改页面的@model,将List对象改为PageList对象。

using声明能够访问MVC的辅助方法。

默认提交数据方式为POST,这表示在http消息体中传入的查询字符串参数而不是在URL中传入。当指定HTTP GET,表单数据会以URL作为查询字符串传入这样会使用户看到URL参数,在中提到,当Action不是update时推荐使用GET。

使用当前查询字符串初始化文本框。当点击新页面时可以看到当前查询字符串。

Find by Name:@Html.TextBox("searchStr", ViewBag.CurrentFilter as string)

列标题连接使用查询字符串把关键字传递给控制器,这样用户就可以对查询出的结果进行排序。

@Html.ActionLink("LastName", "Index", new { sortOrder = ViewBag.NameSort, currentFilter = ViewBag.CurrentFilter })

显示当前页和总页数

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

使用PagedListPager的辅助方法显示分页按钮。

@Html.PagedListPager( Model, page => Url.Action("Index", new { page }) )

创建About页面显示学生统计信息

在这个页面中,将要显示每学期有多少学生入学,这用到了分组和简单的分组计算。接下来将要做:

  • 创建需要传递给视图用的模型类
  • 修改HomeController中的About方法
  • 修改About视图页面
创建视图模型

在项目中添加ViewModels文件夹,在此文件夹中添加类EnrollmentDateGroup.cs。代码如下:

1 using System; 2 using System.ComponentModel.DataAnnotations; 3  4 namespace ContosoUniversity.ViewModels 5 { 6     public class EnrollmentDateGroup 7     { 8         [DataType(DataType.Date)] 9         public DateTime? EnrollmentDate { get; set; }10         public int StudentCount { get; set; }11     }12 }
修改HomeController

在Home控制器中添加引用:

using ContosoUniversity.DAL;using ContosoUniversity.ViewModels;

添加数据库上下文:

public class HomeController : Controller    {        private SchoolContext db = new SchoolContext();

修改About方法:

public ActionResult About()        {                      IQueryable
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查询:根据入学登记日期对学生信息分组,同时计算每组的学生人数,并将结果存储在EnrollmentDateGroup视图模型对象中。

添加Dispose方法:

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

修改About视图

@model IEnumerable< ContosoUniversity.ViewModels.EnrollmentDateGroup>@{    ViewBag.Title = "学生统计";}

学生统计

@foreach (var item in Model) {
}
Enrollment Date Students
@Html.DisplayFor(modelItem => item.EnrollmentDate) @item.StudentCount

Use this area to provide additional information.

运行页面,ok。本节完!

 

转载于:https://www.cnblogs.com/peaceOfMind/p/5328725.html

你可能感兴趣的文章
java中给main传参的方式
查看>>
Git常用
查看>>
springboot实现邮件发送
查看>>
Python3.x:抢票
查看>>
前端三大主流框架的对比React、Vue、Angular 所谓是是三分天下
查看>>
12数据结构与算法分析之---顺序栈
查看>>
33数据结构与算法分析之---图的遍历
查看>>
spring log4j日志处理
查看>>
【转】 XCode的一些调试技巧
查看>>
给定一个数组,获取数组中的最大值,以及最小值。
查看>>
python中filter函数
查看>>
Python3基础8——for循环
查看>>
搜索引擎elasticsearch常用指令演示
查看>>
4-监听器
查看>>
环境的搭建(一)
查看>>
Python--面向对象的程序设计之组合应用、开发软件规范
查看>>
java内部类总结(转)
查看>>
静态变量、全局变量和局部变量
查看>>
配置Eclipse使用TFS源码管理
查看>>
c++vs报错缺少显式类型-假定为int的 三种可能性
查看>>