《Entity Framework 6 Recipes》中文翻譯系列 (21) -----第四章 ASP.NET MVC中使用實體框架之在頁面中建立查詢和使用ASP.NET URL路由過慮

翻譯的初衷以及爲何選擇《Entity Framework 6 Recipes》來學習,請看本系列開篇html

4.2. 構建一個搜索查詢

  搜索數據是幾乎全部應用的一個基本功能。它通常是動態的,由於用戶可能使用提供的任何一個條件,或者一個也不使用。因此,咱們在下面討論實現這個基本功能的一些細節。數據庫

問題編程

  你想在ASP.NET MVC4中使用實體框架構建一搜索頁面。瀏覽器

 

解決方案架構

  假設你有如圖4-14所示的模型,在這個解決方案中,咱們打算使用三個基本的部分來構建搜索頁:框架

    一、一張用於構造查詢參數的表;函數

    二、一個用於在Razor視圖中呈現結果的WebGrid;學習

    三、一個包含視圖邏輯的Cotroller;測試

  在數據庫中,你有一張Customer表,它存儲全部客戶的Name,City和State信息。Customer表的數據模型(架構)如圖4-14所示。優化

 

圖4-14 一個包含Customer 實體的模型

   

   在Customer視圖模型被建立以後,咱們須要使用Razor來編寫視圖。在這個視圖中,咱們使用WebGrid控件來顯示Customer記錄。如代碼清單4-5所示。

代碼清單4-5. 在MVC Razor視圖中使用WebGrid

 1 @model EntityFrameworkRecipe2.ViewModels.CustomerVM
 2 
 3 @{
 4     Layout = null;
 5 }
 6 
 7 @{
 8     ViewBag.Title = "Customer";
 9     WebGrid grid = new WebGrid(canPage:false,canSort:false);
10     grid.Bind(Model.Customers, 
11               autoSortAndPage: false
12     ); 
13 }
14 
15 @using (Html.BeginForm())
16 {
17 <table>
18     <tr>
19         <td>
20             Name
21         </td>    
22         <td>
23             @Html.TextBoxFor(model => model.Name)
24         </td>
25     </tr>
26     <tr>
27         <td>
28             City
29         </td>
30         <td>
31             @Html.TextBoxFor(model => model.City)
32         </td>
33     </tr>
34     <tr>
35         <td>
36             State
37         </td>
38         <td>
39             @Html.TextBoxFor(model => model.State)
40         </td>
41     </tr>
42     <tr>            
43         <td colspan="2">
44             <input type="submit" id="search" title="Search" value="Search" />
45         </td>
46     </tr>
47 </table>
48 <div id="searchResults">
49         <!-- placeHolder for search results -->
50         @grid.GetHtml(
51             fillEmptyRows: true,
52             alternatingRowStyle: "alternate-row",
53             headerStyle: "grid-header",
54             footerStyle: "grid-footer",
55             columns: new [] {
56                 grid.Column("Name"),
57                 grid.Column("City"),
58                 grid.Column("State")
59         })
60 </div>
61 }

  一旦視圖編寫好,我就開始在Controller中編寫支持Get和Post方式的查詢功能。咱們打算將從數據庫中獲取的Customer數據放到 view modle中,實現如代碼清單4-6所示.

代碼清單4-6. 獲取數據代搜索頁測試

 1  public class CustomerController : Controller
 2     {
 3         public ActionResult Search()
 4         {
 5             using (var db = new CustomerEntities())
 6             {
 7                 var customer = db.Customers.ToList();
 8                 var data = new CustomerVM()
 9                 {
10                     Customers = customer
11                 };
12                 return View(data);
13             }
14         }
15         [HttpPost]
16         public ActionResult Search(CustomerVM customerVmValue)
17         {
18             using (var db = new CustomerEntities())
19             {
20                 var customerSearchResults = from customerRec in db.Customers
21                                              where ((customerVmValue.Name == null) || (customerRec.Name == customerVmValue.Name.Trim()))
22                                              && ((customerVmValue.City == null) || (customerRec.City == customerVmValue.City.Trim()))
23                                              && ((customerVmValue.State == null) || (customerRec.State == customerVmValue.State.Trim()))
24                                              select new
25                                              {
26                                                  Name = customerRec.Name
27                                                  ,
28                                                  City = customerRec.City
29                                                  ,
30                                                  State = customerRec.State
31                                              };
32                 List<Customer> lstCustomer = new  List<Customer>();
33                 foreach (var record in customerSearchResults)
34                 {
35                     Customer customerValue = new Customer();
36                     customerValue.Name = record.Name;
37                     customerValue.City = record.City;
38                     customerValue.State = record.State;
39                     lstCustomer.Add(customerValue);
40                 }
41                 customerVmValue.Customers = lstCustomer;
42                 return View(customerVmValue);
43             }
44         }
45     }

 

   你在你的瀏覽器中,頁面呈現如圖4-15所示:

圖4-15 瀏覽器中呈現的視圖

 

原理

   在頁面的第一小節中(請看代碼清單4-5),咱們使用table來格式化查詢字段,這裏沒有花俏的技術,咱們只是提供了獲取三個查詢字段:Name,City和State的結構。他們的值(或者沒有),將用於查詢按鈕被點擊了以後Controller的查詢(Search)動做方法.所以,這些參數會成爲查詢的過慮條件。

  接下來,咱們使用HtmlHelper在WebGrid控件中顯示結果集。數據源使用view model。這裏須要注意,咱們建立了兩個模型,一個用於從數據庫中獲取數據,一個用於視圖頁收集查詢參數,和呈現結果集。

  咱們使用Linq to entities來查詢數據模型中的Customer實體,where從句和參數肯定了咱們的查詢過濾。在視圖中,咱們將查詢參數Name,City和State映射到 HtmlHelper中的文本框。將Name屬性映射到文件框Name,依次類推。

  咱們使用控件WebGrid來顯示結果集,它被綁定到CustomerVM.Customers列表,它是專門用來獲取查詢結果集的。

  代碼清單4-6中所展現的controller代碼,從數據庫中獲取數據,並在第一次加載視圖和點擊查詢按鈕後填充視圖。咱們使用了本地數據庫.mdf文件並在Customer表中填充了記錄。

 

 

4.3. 使用ASP.NET的URL路由過慮

問題

  你想使用MapRoute來簡化你的URLs,同時你想憑藉這位路由在Razor視圖引擎中過濾結果集。

解決方案

  假設你有如圖4-16的模型,咱們已經對產品以及它們的目錄建模,用實體類型Product來表示產品。在一個典型的電商網站中,咱們須要按目錄對產品進行分類。咱們要避免在URLs中暴露相似 "/Product/Index?Category=Tents"這樣的查詢字符串。雖然這樣會使編程簡單一些,但無益於搜索引擎優化。咱們須要看起像 「/Producs/Tents"這樣的URLs.

圖4-6  一個包含products和它們的categories

  咱們能經過路由獲得對搜索引擎友好的URL,路由通常在Global.asax的Application_Start()事件處理函數中建立。代碼清單4-7演示了爲Product控制器添加一條路由。

代碼清單4-7. 在Global.asax中建立一條路由

 1 protected void Application_Start()
 2         {
 3             AreaRegistration.RegisterAllAreas();
 4 
 5             WebApiConfig.Register(GlobalConfiguration.Configuration);
 6             FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
 7             RouteTable.Routes.MapRoute("Product", "{controller}/{name}",
 8                                 new { controller = "Product", action = "Index" }
 9                             );
10             RouteConfig.RegisterRoutes(RouteTable.Routes);
11             BundleConfig.RegisterBundles(BundleTable.Bundles);
12             AuthConfig.RegisterAuth();
13         }

  在代碼清單4-8所示的Index視圖中,咱們使用category name綁定到Product controller中的Inde動做方法的name參數,如代碼清單4-7所示。咱們使用代碼清單4-9中的代碼獲取category name參數的值,並經過視圖處理結果集。圖4-17和圖4-18分別展現了呈現Tents目錄下產品的視圖頁面,和Cooking Equipment目錄下產品的視圖頁面。

代碼清單4-8. Index視圖代碼,它顯示經過目錄過濾後的產品

 1 @model IEnumerable<EntityFrameworkRecipe3.ViewModels.ProductVM>
 2 
 3 @{
 4     Layout = null;
 5 }
 6 
 7 <!DOCTYPE html>
 8 
 9 <html>
10 <head>
11     <meta name="viewport" content="width=device-width" />
12     <title>Index</title>
13 </head>
14 <body>
15     <table>
16         <tr>
17             <th>
18                 @Html.DisplayNameFor(model => model.Name)
19             </th>
20             <th>
21                 @Html.DisplayNameFor(model => model.CategoryName)
22             </th>
23             <th></th>
24         </tr>
25     
26     @foreach (var item in Model) {
27         <tr>
28             <td>
29                 @Html.DisplayFor(modelItem => item.Name)
30             </td>
31             <td>
32                 @Html.DisplayFor(modelItem => item.CategoryName)
33             </td>
34         </tr>
35     }
36     
37     </table>
38 </body>
39 </html>

代碼清單4-9. Controller代碼,使用經過Category Name過濾後的Product數據填充模型

 1 public class ProductController : Controller
 2     {
 3         //
 4         // GET: /Product/
 5 
 6         public ActionResult Index(string name)
 7         {
 8             using (var db = new ProductEntities())
 9             {
10                 var query = from productRec in db.Products
11                             join categoryRec in db.Categories
12                             on productRec.CategoryId
13                             equals categoryRec.CategoryId
14                             where categoryRec.Name == name
15                             select new
16                             {
17                                 Name = productRec.Name
18                                 ,
19                                 CategoryName = categoryRec.Name
20                             };
21                 List<ProductVM> lstProduct = new List<ProductVM>();
22                 foreach(var record in query)
23                 {
24                     ProductVM productValue = new ProductVM();
25                     productValue.Name = record.Name;
26                     productValue.CategoryName = record.CategoryName;
27                     lstProduct.Add(productValue);
28                 }
29                 return View(lstProduct);
30             }
31         }
32 
33     }

圖4-17 使用路徑「/Product/Tents",獲得Tents目錄類別的產品集

圖4-18 使用路徑「/Product/cooking Equipment"獲得cooking Equipment目錄類別的產品集

 

原理

  在Global.asax中 Applicate_Start()事件處理函數中,咱們爲以前的"/Product/Index?name=category"映射了路由 "/Product/{name}".在Product controller中,咱們使用MapRoute中的路由key,name,過濾結果集,經過給定的目錄過濾產品。

 

  至此,第四章結束,感謝你的閱讀。下一篇,咱們將進入第五章的學習。


 

 

實體框架交流QQ羣:  458326058,歡迎有興趣的朋友加入一塊兒交流

謝謝你們的持續關注,個人博客地址:http://www.cnblogs.com/VolcanoCloud/

相關文章
相關標籤/搜索