MVC3+EF4.1學(xué)習(xí)系列(三)-----排序 刷選 以及分頁
上篇文章 已經(jīng)做出了基本的增刪改查 但這遠(yuǎn)遠(yuǎn)不足以應(yīng)付實(shí)際的項(xiàng)目 今天講下實(shí)際項(xiàng)目中 肯定會有的 排序 刷選 以及分頁。 重點(diǎn)想多寫點(diǎn)分頁的 畢竟這個(gè)是任何時(shí)候都要有的
而且 我會盡量把這個(gè)分頁做的復(fù)雜下 這樣到實(shí)際項(xiàng)目時(shí) 可以復(fù)制過來改改就行了~~ (這里我用的是國產(chǎn)的基于ScottGu的PagedList<T>類和相關(guān)方法完善的分頁--MVCPager)
是個(gè)開源的 帶很多demo介紹的分頁幫助類 這里說下 建議大家看下源碼 這樣才能進(jìn)步 要不然只是個(gè)會使用插件的人~ 在這里感謝下作者 ~~ 好了 開始先上效果圖

這個(gè)樣式可以調(diào)~~ 我的樣子難看了些~~ 顯示當(dāng)前頁的索引 記錄條數(shù) 還有跳轉(zhuǎn)頁數(shù) 等 常用分頁的功能都有了
我們可以根據(jù)姓名查找 可以點(diǎn)擊 lastName 按姓名排序 和按發(fā)布日期排序 這就是今天要做的~
一.排序
public ViewResult 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.EnrollmentDate);
break;
}
return View(students.ToList());
}
這亂七八糟的是什么呢 我來解釋下~ 接受的參數(shù)sortOrder是根據(jù)什么排序 例如http://localhost:2175/Student?sortOrder=Date 就是根據(jù)時(shí)間升序排列
我們可以先不看前兩行 先看后面的
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.EnrollmentDate);
break;
}
先來說下 這不是把所有記錄都查出來 然后再排序 因?yàn)檫@個(gè)是IQueryable 的 這個(gè)是將表達(dá)式樹 翻譯成SQL 最后再執(zhí)行的 所以在后面的 根據(jù)條件刷選 分頁 排序等 是不會有效率問題的 但是如果你把上面的students.tolist() 一下 則就是全部加載啦~~ 因?yàn)椴辉偈?IQueryable接口了~~ 也就是說 他是在tolist時(shí)或者說 是在AsEnumerable才執(zhí)行sql~~
好 回到例子上 因?yàn)榈谝淮卧L問 sortOrder一定是空的 所以switch到 students = students.OrderBy(s => s.EnrollmentDate); 默認(rèn)按時(shí)間排序
這時(shí)我們再來看這兩句
ViewBag.NameSortParm = String.IsNullOrEmpty(sortOrder) ? "Name desc" : "";
ViewBag.DateSortParm = sortOrder == "Date" ? "Date desc" : "Date";
viewBag MVC3才有的 利用了.net4.0的 dynamic 特性~ 其實(shí)這個(gè)和MVC2中的 viewdata使用方法差不多 我們在這里 設(shè)置 ViewBag.NameSortParm以及ViewBag.DateSortParm 是為了給view用的 一會兒看view就明白了~ 上來由于sortOrder為空 所以 ViewBag.NameSortParm=Name desc 由于sortOrder 不等于Date 所以
ViewBag.DateSortParm等于 Date
說白了 以時(shí)間排序?yàn)槔?nbsp; 就是為了實(shí)現(xiàn) 點(diǎn)排序連接時(shí) 第一次 升序 再點(diǎn)就變成降序了 再點(diǎn)就變成升序........
不看view 怎么解釋都迷糊~~ 看view
<tr>
<th></th>
<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>
</tr>
不明白就自己做下 動(dòng)動(dòng)手~~ 調(diào)試幾次就明白了~
二.根據(jù)條件過濾
這里我們做的是根據(jù)姓名刷選
我們先在index視圖下加個(gè)搜索框和搜索按鈕
@using (Html.BeginForm())
{
<p>
Find by name: @Html.TextBox("SearchString")
<input type="submit" value="Search" /></p>
}
我們的控制器更改為
View Code
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());
}
Index方法多了個(gè)參數(shù) SearchSring 這個(gè)參數(shù)名字是和 Html.TextBox 里的name對應(yīng)著的
并且增加如下代碼
if (!String.IsNullOrEmpty(searchString))
{
students = students.Where(s => s.LastName.ToUpper().Contains(searchString.ToUpper())
|| s.FirstMidName.ToUpper().Contains(searchString.ToUpper()));
}
查看姓名里是否含有要搜索的
這樣 條件過濾就完成了
但是有個(gè)小問題 我們一般搜索完 文本框保留搜索內(nèi)容 而不是沒了 所以這里需要再次借用ViewBag.Filter = searchString; 保存下值
然后視圖改為
<p>Find by Name @Html.TextBox("searchString", ViewBag.Filter as string)</p>
好了 這樣搜索就完了~~接下來 最重要的分頁
三.分頁
接下來是講MVCPager
首先 下去下載例子以及DLL 這里有個(gè)問題 就是下載的dll和mvc3不是很兼容 讓我糾結(jié)了很久 要去下載mvc3的實(shí)例 然后把里面的 一個(gè)叫做MvcPager的dll找到 添加這個(gè)引用就OK了
然后我們打開view下的config 添加命名空間 這樣可以讓你的view都有這個(gè)命名空間了~
<system.web.webPages.razor>
<host factoryType="System.Web.Mvc.MvcWebRazorHostFactory, System.Web.Mvc, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
<pages pageBaseType="System.Web.Mvc.WebViewPage">
<namespaces>
<add namespace="System.Web.Mvc" />
<add namespace="System.Web.Mvc.Ajax" />
<add namespace="System.Web.Mvc.Html" />
<add namespace="System.Web.Routing" />
<add namespace="Webdiyer.WebControls.Mvc"/><!--添加這個(gè) -->
</namespaces>
</pages>
</system.web.webPages.razor>
改造我們的控制器 如下
View Code
public ActionResult Index(string sortOrder,string searchString,int? page=1)
{
ViewBag.NameSortParm = string.IsNullOrEmpty(sortOrder) ? "Name desc" : "";
ViewBag.DateSortParm = sortOrder == "Date" ? "Date desc" : "Date";
var students = from s in db.Students
select s;
ViewBag.Filter = searchString;
if (!string.IsNullOrEmpty(searchString))
{
students=students.Where(s => s.FirstMidName.ToUpper().Contains(searchString) || s.LastName.ToUpper().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.EnrollmentDate);
break;
}
int pageSize = 2;
int pageIndex = page ?? 1;
return View(students.ToPagedList(pageIndex, pageSize));
}
要記得 pageIndex 從1開始 1表示第一頁
只需簡單的返回
int pageSize = 2;
int pageIndex = page ?? 1;
return View(students.ToPagedList(pageIndex, pageSize));
這樣就OK了 就這么簡單~~
視圖的model 改為 @model PagedList<ContosoUniversity.Models.Student>
然后分頁的視圖為
<p>共有 @Model.TotalItemCount 條記錄 @Model.CurrentPageIndex/@Model.TotalPageCount</p>
@Html.Pager(Model, new PagerOptions { PageIndexParameterName = "page", ShowPageIndexBox = true, PageIndexBoxType = PageIndexBoxType.TextBox, PageIndexBoxWrapperFormatString = "請輸入頁數(shù){0}" }, "Default", new { sortOrder = ViewBag.DateSortParm, searchString = ViewBag.Filter })
看 一個(gè)要顯示復(fù)雜的分頁 就這么簡單的完成了
大家一定和我一樣 關(guān)心生成的SQL語句怎么樣 是否靠譜 效率可以么 讓我們監(jiān)控一下生成的SQL語句吧
這是通過跟蹤得到的SQL
SELECT TOP (2)
[Extent1].[StudentID] AS [StudentID],
[Extent1].[LastName] AS [LastName],
[Extent1].[FirstMidName] AS [FirstMidName],
[Extent1].[EnrollmentDate] AS [EnrollmentDate]
FROM ( SELECT [Extent1].[StudentID] AS [StudentID], [Extent1].[LastName] AS [LastName], [Extent1].[FirstMidName] AS [FirstMidName], [Extent1].[EnrollmentDate] AS [EnrollmentDate], row_number() OVER (ORDER BY [Extent1].[EnrollmentDate] ASC) AS [row_number]
FROM [dbo].[Student] AS [Extent1]
) AS [Extent1]
WHERE [Extent1].[row_number] > 2
ORDER BY [Extent1].[EnrollmentDate] ASC
利用 row_number() 實(shí)現(xiàn)的分頁 ~~
好了 分頁OK了
四.總結(jié)
基本的EF操作OK了 合理利用第三方插件 大大提高了開發(fā)效率 學(xué)會借用 但也要知道原理
EF做為ORM 框架 就是要處理關(guān)系 前面這幾篇 都是簡單的操作 沒有設(shè)計(jì)關(guān)系
下篇講ORM的關(guān)系的處理 不僅是EF ORM框架都會遇到的 關(guān)系的處理 以及 多對多關(guān)系表里還需要其他字段時(shí)的處理
轉(zhuǎn)載 請保留連接~~

浙公網(wǎng)安備 33010602011771號