翻譯的初衷以及為什么選擇《Entity Framework 6 Recipes》來學習,請看本系列開篇
第四章 ASP.NET MVC中使用實體框架
ASP.NET是一個免費的Web框架,它支持3種不同的技術來創建websites(網站)和Web應用;他們分別是,Web Pages,Web Forms,和MVC。雖然MVC是一種非常流行的,有完整的用於軟件開發模式理論的技術,但它在ASP.NET中卻是一種新的技術。 目前最新的版本是2012年發布的ASP.NET MVC4。自從2008年發布最初的版本后,它已經變成繼ASP.NET Web-Forms后的一種流行的開發方式。因此,本章將展示ASP.NET MVC4和實體框架的開發技巧,不覆蓋ASP.NET中另外兩種技術---ASP.NET Web Forms和ASP.NET Web Pages。
本章將全面地介紹構建一個包含插入、更新、刪除和實現列表頁搜索的應用。
本章的每一技巧都是使用Visual Studio2012中的ASP.NET MVC4 Web應用來展示,我們盡可能地保持示例的簡單,因此不打算包含默認模板中的所有功能。
4.1. 構建一個包含CRUD操作的ASP.NET MVC頁
創建、讀取、更新、刪除(CRUD)操作,幾乎是所有軟件應用最基本的功能。我們打算在本節使用ASP.NET MVC來實現這些操作。
問題
你想一個ASP.NET MVC頁,它能從模型中插入、更新、刪除和讀取數據。
解決方案
假設你有一個Web 應用 ,它管理着一個移動應用的app列表。你有如圖4-1所示的模型。
圖4-1 一個包含Category實體類型的模型,該實體類型包含一個應用目錄名(Name)和描述(Description)屬性
這個模型包含一個category實體類型,你想創建一個簡單的ASP.NET MVC 頁面來展示app的目錄列表。同時,你允許用戶創建一個新的app目錄,更新和刪除一個存在的目錄。雖然有很多方式可以實現這個需求,但我們將采用一種非常簡單的方式,讓你理解在ASP.NET MVC中集成實體框架。為了創建一個MVC應用,你需要三個部分,一個model,一個controller和一個view. 我們將使用文件MyStore.mdf作為我們數據庫。我們將在視圖中使用Razor視圖引擎。依據動作或操作的需要,雖然只需要一個model,但會有多個views。在我們的示例中,我們將使用4個視圖,一個用於創建,一個用於更新,一個用於刪除,一個用於列表顯示。
首先,我們要創建一個ASP.NET MVC4 的Web應用,如圖4-2和4-3所演示的,我將使用項目模板Internet Application。
圖4-2 在Visua Studio2012中選擇ASP.NET MVC Web Application 項目
圖4-3 選擇項目模型 ASP.NET MVC application
一個新的帶了一些默認文件和文件夾的項目被創建了。
現在可以為應用准備數據庫了,為了使示例簡單清晰,我們在項目中使用數據庫文件MyStore.mdf。
在Visual Studio開發環境中,很容易創建MDF格式的數據庫文件,這個文件能被附加到SQL Server Experess實例中,並像正常的,完整的數據一樣使用。不同之處在於,這只是通過數據庫連接字符串附加,並不是永久地將其附加到SQL Server的實例中。
右鍵文件夾App_Data並添加一個新的.mdf文件,這個文件可以用兩種方式添加 ,在Add上下文添加中選擇New Item(新建項),如圖4-4所示,或者選擇 SQL Server Database,如圖4-5所示。
圖4-5 在app_data文件夾中添加新項
圖4-5 選擇一個SQL Server Database文件作為新建項添加
在.mdf文件中創建三張表后,我們使用實體框架生成一個新的模型,如圖4-6所示
圖4-6 三張表及其他們之前的關聯
這個模型是能過添加ADO.NET Entity Data Model到你的項目的Models文件夾中生成的,如圖4-7所示:
圖4-7 添加一個實體數據模型
正如我們在前面討論的那樣,ASP.NET MVC應用需要三個部分,model,view 和controller。我已經完成對model部分的創建。接下來,我們需要創建一個controller,最后創建 views。views的數量,由controller中執行的動作來決定。
如圖4-8所示,添加一個controller,右鍵Controllers文件夾,然后選擇添加一個Controller,並命名為CategoryController.
圖4-8 添加一個controller
正如你看到的那樣,我們在添加CategoryCntroller的窗口中選擇了模板 empty read/write actions。它會在controller中創建一些動作方法。需要使用的數據庫上下文如代碼清單4-1所示。
代碼清單4-1. 繼承自DbContext類的上下文對象,它將使用實體框架在數據庫執行操作
1 public partial class MyStoreEntities : DbContext 2 { 3 public MyStoreEntities() 4 : base("name=MyStoreEntities") 5 { 6 } 7 8 protected override void OnModelCreating(DbModelBuilder modelBuilder) 9 { 10 throw new UnintentionalCodeFirstException(); 11 } 12 13 public DbSet<App> Apps { get; set; } 14 public DbSet<Category> Categories { get; set; } 15 public DbSet<Developer> Developers { get; set; } 16 }
如代碼清單4-2所示,我們修改了控制器中的代碼,使它能通過DbContext類執行插入、刪除 、編輯和顯示。
1 // 2 // GET: /Category/ 3 4 public ActionResult Index() 5 { 6 using (var db = new MyStoreEntities()) 7 { 8 return View(db.Categories.ToList()); 9 } 10 } 11 12 // 13 // GET: /Category/Details/5 14 15 public ActionResult Details(int id) 16 { 17 using (var db = new MyStoreEntities()) 18 { 19 return View(db.Categories.Find(id)); 20 } 21 } 22 23 // 24 // GET: /Category/Create 25 26 public ActionResult Create() 27 { 28 return View(); 29 } 30 31 // 32 // POST: /Category/Create 33 34 [HttpPost] 35 public ActionResult Create(Category categoryValue) 36 { 37 try 38 { 39 using (var db = new MyStoreEntities()) 40 { 41 db.Categories.Add(categoryValue); 42 db.SaveChanges(); 43 } 44 return RedirectToAction("Index"); 45 } 46 catch 47 { 48 return View(); 49 } 50 } 51 52 // 53 // GET: /Category/Edit/5 54 55 public ActionResult Edit(int id) 56 { 57 using (var db = new MyStoreEntities()) 58 { 59 return View(db.Categories.Find(id)); 60 } 61 } 62 63 // 64 // POST: /Category/Edit/5 65 66 [HttpPost] 67 public ActionResult Edit(int id, Category categoryValue) 68 { 69 try 70 { 71 using (var db = new MyStoreEntities()) 72 { 73 db.Entry(categoryValue).State = System.Data.Entity.EntityState.Modified; 74 db.SaveChanges(); 75 return RedirectToAction("Index"); 76 } 77 } 78 catch 79 { 80 return View(); 81 } 82 } 83 84 // 85 // GET: /Category/Delete/5 86 87 public ActionResult Delete(int id) 88 { 89 using (var db = new MyStoreEntities()) 90 { 91 return View(db.Categories.Find(id)); 92 } 93 } 94 95 // 96 // POST: /Category/Delete/5 97 98 [HttpPost] 99 public ActionResult Delete(int id, Category categoryValue) 100 { 101 try 102 { 103 using (var db = new MyStoreEntities()) 104 { 105 db.Entry(categoryValue).State = System.Data.Entity.EntityState.Deleted; 106 db.SaveChanges(); 107 return RedirectToAction("Index"); 108 } 109 } 110 catch 111 { 112 return View(); 113 } 114 }
為CategoryController中的動作,新建、刪除、明細、編輯和Index添加五個視圖。你可以按圖4-9所示添加視圖,在controller里的動作方法上右鍵並選擇AddView。這樣一個新的視圖將被添加到Views ➤Category文件夾。
圖4-9 通過在controller中的動作方法添加視圖
在添加視圖的對話框,如圖4-10所示,選擇Razor視圖引擎(CSHTML),然后勾選上創建一個強類型的視圖,最后選擇Category(MyStore.Models)類作為Model.
圖4-10 添加一個視圖
代碼清單4-3中的Index視圖,是一個顯示app目錄的視圖頁,它上面有New(新建)按鈕,editing(編輯)按鈕、deleting(刪除)按鈕。代碼清單4-4創建的視圖頁用來插入一個應用目錄。
代碼清單4-3. Index視圖代碼
1 @model IEnumerable<MyStore.Models.Category> 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 <p> 16 @Html.ActionLink("Create New", "Create") 17 </p> 18 <table> 19 <tr> 20 <th> 21 @Html.DisplayNameFor(model => model.Name) 22 </th> 23 <th> 24 @Html.DisplayNameFor(model => model.Description) 25 </th> 26 <th></th> 27 </tr> 28 29 @foreach (var item in Model) { 30 <tr> 31 <td> 32 @Html.DisplayFor(modelItem => item.Name) 33 </td> 34 <td> 35 @Html.DisplayFor(modelItem => item.Description) 36 </td> 37 <td> 38 @Html.ActionLink("Edit", "Edit", new { id=item.CategoryId }) | 39 @Html.ActionLink("Details", "Details", new { id=item.CategoryId }) | 40 @Html.ActionLink("Delete", "Delete", new { id=item.CategoryId }) 41 </td> 42 </tr> 43 } 44 45 </table> 46 </body> 47 </html>
代碼清單4-4. Create視圖代碼
1 @model MyStore.Models.Category 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>Create</title> 13 </head> 14 <body> 15 <script src="~/Scripts/jquery-1.8.2.min.js"></script> 16 <script src="~/Scripts/jquery.validate.min.js"></script> 17 <script src="~/Scripts/jquery.validate.unobtrusive.min.js"></script> 18 19 @using (Html.BeginForm()) { 20 @Html.AntiForgeryToken() 21 @Html.ValidationSummary(true) 22 23 <fieldset> 24 <legend>Category</legend> 25 26 <div class="editor-label"> 27 @Html.LabelFor(model => model.Name) 28 </div> 29 <div class="editor-field"> 30 @Html.EditorFor(model => model.Name) 31 @Html.ValidationMessageFor(model => model.Name) 32 </div> 33 34 <div class="editor-label"> 35 @Html.LabelFor(model => model.Description) 36 </div> 37 <div class="editor-field"> 38 @Html.EditorFor(model => model.Description) 39 @Html.ValidationMessageFor(model => model.Description) 40 </div> 41 42 <p> 43 <input type="submit" value="Create" /> 44 </p> 45 </fieldset> 46 } 47 48 <div> 49 @Html.ActionLink("Back to List", "Index") 50 </div> 51 </body> 52 </html>
代碼清單4-3中的代碼顯示了一個app目錄列表視圖頁,以及插入目錄,編輯、刪除當前目錄的按鈕。該頁的效果如圖4-11所示。
圖4-11 app目錄列表
圖4-12所示的,文本框允許用戶輸入目錄信息,點擊Create按鈕,將會在數據庫中添加一條新的記錄。
圖4-12 插入一個新的app目錄
如圖4-13所示,在Index視圖上單擊Edit按鈕,將會顯示允許你編輯一個存在的app目錄的視圖頁。
圖4-13 編輯一個app目錄
原理
整個代碼分為三個部分:
1、上下文對象類(代碼清單4-1);
2、Controller代碼(代碼清單4-2);
3、視圖代碼(代碼清單4-3,4-4);
controller代碼是最大的一部分,它提供了整個操作的核心功能。視圖是基於Controller中的動作方法創建的。所有的獲取,創建,更新,刪除都是在動作方法中處理。視圖無論是通過URL或是另一個視圖訪問,相應的controller中的動作方法都會被調用。我們在創建視圖時選擇了scaffoleding 選項。通過選擇這個選項,它會使用razor視圖引擎自動生成編輯、創建 、和顯示列表的HTML代碼。
本篇有點長,主要是圖有點多,辛苦大家了,感謝你們的閱讀!
完整示例,請在群共享下載,文件大小超過了博客園的限制,所以這里提供不了下載。
實體框架交流QQ群: 458326058,歡迎有興趣的朋友加入一起交流
謝謝大家的持續關注,我的博客地址:http://www.cnblogs.com/VolcanoCloud/