MVC3+EF4.1學習系列(三)-----排序 刷選 以及分頁

上篇文章 已經作出了基本的增刪改查    但這遠遠不足以應付實際的項目  今天講下實際項目中 確定會有的 排序 刷選  以及分頁。 重點想多寫點分頁的 畢竟這個是任什麼時候候都要有的html

並且 我會盡可能把這個分頁作的複雜下  這樣到實際項目時 能夠複製過來改改就好了~~ (這裏我用的是國產的基於ScottGu的PagedList<T>類和相關方法完善的分頁--MVCPager)web

是個開源的  帶不少demo介紹的分頁幫助類  這裏說下 建議你們看下源碼 這樣才能進步 要否則只是個會使用插件的人~   在這裏感謝下做者 ~~ 好了 開始先上效果圖sql

這個樣式能夠調~~  個人樣子難看了些~~    顯示當前頁的索引 記錄條數 還有跳轉頁數  等 經常使用分頁的功能都有了mvc

咱們能夠根據姓名查找  能夠點擊 lastName 按姓名排序  和按發佈日期排序  這就是今天要作的~app

一.排序框架

複製代碼

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

複製代碼

這亂七八糟的是什麼呢  我來解釋下~  接受的參數sortOrder是根據什麼排序   例如http://localhost:2175/Student?sortOrder=Date   就是根據時間升序排列
asp.net

 咱們能夠先不看前兩行 先看後面的spa

複製代碼

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

複製代碼

先來講下 這不是把全部記錄都查出來 而後再排序  由於這個是IQueryable 的  這個是將表達式樹 翻譯成SQL 最後再執行的  因此在後面的 根據條件刷選 分頁 排序等 是不會有效率問題的   可是若是你把上面的students.tolist() 一下 則就是所有加載啦~~  由於再也不是IQueryable接口了~~  也就是說 他是在tolist時或者說 是在AsEnumerable才執行sql~~
.net

好 回到例子上  由於第一次訪問  sortOrder必定是空的 因此switch到  students = students.OrderBy(s => s.EnrollmentDate);  默認按時間排序插件

這時咱們再來看這兩句


ViewBag.NameSortParm = String.IsNullOrEmpty(sortOrder) ? "Name desc" : "";
ViewBag.DateSortParm
= sortOrder == "Date" ? "Date desc" : "Date";

viewBag  MVC3纔有的   利用了.net4.0的 dynamic 特性~  其實這個和MVC2中的 viewdata使用方法差很少  咱們在這裏 設置  ViewBag.NameSortParm以及ViewBag.DateSortParm 是爲了給view用的  一下子看view就明白了~    上來因爲sortOrder爲空  因此ViewBag.NameSortParm=Name desc   因爲sortOrder 不等於Date 因此

ViewBag.DateSortParm等於 Date  

說白了  以時間排序爲例  就是爲了實現 點排序鏈接時   第一次 升序  再點就變成降序了  再點就變成升序........

不看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>

不明白就本身作下 動動手~~ 調試幾回就明白了~

二.根據條件過濾

這裏咱們作的是根據姓名刷選

咱們先在index視圖下加個搜索框和搜索按鈕

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

咱們的控制器更改成

複製代碼

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方法多了個參數 SearchSring  這個參數名字是和 Html.TextBox 裏的name對應着的 

而且增長以下代碼

if (!String.IsNullOrEmpty(searchString))
{
   students
= students.Where(s => s.LastName.ToUpper().Contains(searchString.ToUpper())
                         
|| s.FirstMidName.ToUpper().Contains(searchString.ToUpper()));
}

查看姓名裏是否含有要搜索的

這樣 條件過濾就完成了

可是有個小問題  咱們通常搜索完 文本框保留搜索內容 而不是沒了  因此這裏須要再次借用ViewBag.Filter = searchString;  保存下值

而後視圖改成

 <p>Find by Name @Html.TextBox("searchString", ViewBag.Filter as string)</p>

好了 這樣搜索就完了~~接下來 最重要的分頁

三.分頁

接下來是講MVCPager

首先 下去下載例子以及DLL  這裏有個問題 就是下載的dll和mvc3不是很兼容 讓我糾結了好久  要去下載mvc3的實例  而後把裏面的 一個叫作MvcPager的dll找到 添加這個引用就OK了

而後咱們打開view下的config 添加命名空間 這樣可讓你的view都有這個命名空間了~

複製代碼

  <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"/><!--添加這個 -->
     
</namespaces>
   
</pages>
 
</system.web.webPages.razor>

複製代碼

改造咱們的控制器 以下

複製代碼

  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 = "請輸入頁數{0}" }, "Default", new { sortOrder = ViewBag.DateSortParm, searchString = ViewBag.Filter })

看 一個要顯示覆雜的分頁  就這麼簡單的完成了

你們必定和我同樣 關心生成的SQL語句怎麼樣 是否靠譜 效率能夠麼  讓咱們監控一下生成的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() 實現的分頁 ~~
好了 分頁OK了

四.總結

基本的EF操做OK了  合理利用第三方插件 大大提升了開發效率  學會借用 但也要知道原理

EF作爲ORM 框架 就是要處理關係  前面這幾篇 都是簡單的操做 沒有設計關係

相關文章
相關標籤/搜索