使用 Entity Framework 建立模型類別 (C#)
由 Microsoft 提供
在此教學課程中,您將了解如何搭配 Microsoft Entity Framework 使用 ASP.NET MVC。 您會了解如何使用實體精靈來建立 ADO.NET 實體資料模型。 在此教學課程中,我們會建置 Web 應用程式,說明如何使用 Entity Framework 選取、插入、更新和刪除資料庫資料。
此教學課程的目標是說明如何在建置 ASP.NET MVC 應用程式時,使用 Microsoft Entity Framework 建立資料存取類別。 此教學課程假設先前對 Microsoft Entity Framework 一無所知。 在此教學課程結束時,您將能了解如何使用 Entity Framework 選取、插入、更新和刪除資料庫記錄。
Microsoft Entity Framework 是物件關聯式對應 (O/RM) 工具,可讓您自動從資料庫產生資料存取層。 Entity Framework 可讓您避免手動建置資料存取類別的繁瑣工作。
為了說明如何使用 Microsoft Entity Framework 搭配 ASP.NET MVC,我們將會建置簡單的範例應用程式。 我們會建立電影資料庫應用程式,讓您用於顯示和編輯電影資料庫記錄。
此教學課程假設您擁有 Visual Studio 2008 或 Visual Web Developer 2008 Service Pack 1。 您需要 Service Pack 1 才能使用 Entity Framework。 您可以從下列位址下載 Visual Studio 2008 Service Pack 1 或 Visual Web Developer with Service Pack 1:
注意
ASP.NET MVC 與 Microsoft Entity Framework 之間沒有必需的連線。 您搭配 ASP.NET MVC 使用 Entity Framework 的替代方案有好幾個。 例如,您可以使用其他 O/RM 工具建置 MVC 模型類別,例如 Microsoft LINQ to SQL、NHibernate 或 SubSonic。
建立電影範例資料庫
影片資料庫應用程式會使用名為 Movies 的資料庫資料表,其中包含下列資料行:
資料行名稱 | 資料類型 | 允許 Null? | 主索引鍵? |
---|---|---|---|
Id | int | False | True |
標題 | nvarchar(100) | False | False |
主管 | nvarchar(100) | False | False |
您可以遵循下列步驟,將此資料表新增至 ASP.NET MVC 專案中:
- 在 [方案總管] 視窗中,在 [App_Data] 資料夾按一下滑鼠右鍵,然後選取 [新增]、[新項目] 功能表選項。
- 從 [新增項目] 對話方塊選取 [SQL Server Database],提供資料庫名稱 MoviesDB.mdf,然後按一下 [新增] 按鈕。
- 連按兩下 MoviesDB.mdf 檔案,開啟 [伺服器總管/資料庫總管] 視窗。
- 展開 MoviesDB.mdf 資料庫連結,以滑鼠右鍵按一下 [資料表] 資料夾,然後選取 [新增資料表] 功能表選項。
- 在資料表設計工具中,新增 Id、Title 和 Director 資料行。
- 按一下 [儲存] 按鈕 (有磁碟片圖示),以儲存名為 Movies 的新資料表。
建立 Movies 資料庫資料表之後,您應該將一些範例資料新增至資料表。 以滑鼠右鍵按一下 Movies 資料表,然後選取 [顯示資料表資料] 功能表選項。 您可以在顯示的方格中輸入假的電影資料。
建立 ADO.NET 實體資料模型
若要使用 Entity Framework,您必須建立實體資料模型。 您可以利用 Visual Studio 實體資料模型精靈 ,自動從資料庫產生實體資料模型。
執行下列步驟:
- 在 [方案總管] 視窗中,在 [模型] 資料夾上按滑鼠右鍵,然後選取 [新增]、[新項目] 功能表選項。
- 在 [新增項目] 對話方塊中,選取 [資料] 類別目錄 (參見圖 1)。
- 選取 ADO.NET 實體資料模型範本,將實體資料模型命名為MoviesDBModel.edmx,然後按一下 [新增] 按鈕。 按一下 [新增] 按鈕會啟動 [資料模型精靈]。
- 在 [選擇模型內容] 步驟中,選擇 [從資料庫產生] 選項,然後按 [下一步] 按鈕 (參見圖 2)。
- 在 [選擇您的資料連線] 步驟中,選取 MoviesDB.mdf 資料庫連結,輸入實體連結設定名稱 MoviesDBEntities,然後按 [下一步] 按鈕 (參見圖 3)。
- 在 [選擇您的資料庫物件] 步驟中,選取影片資料庫資料表,然後按一下 [完成] 按鈕 (參見圖 4)。
完成這些步驟之後,ADO.NET 實體資料模型設計工具 (實體設計工具) 隨即開啟。
圖 1 – 建立新的實體資料模型
圖 2 – 選擇模型內容步驟
圖 3 – 選擇您的資料連線
圖 4 – 選擇您的資料庫物件
修改 ADO.NET 實體資料模型
建立實體資料模型之後,您可以利用實體設計工具來修改模型 (參見圖 5)。 您可以隨時按兩下方案總管視窗中 [模型] 資料夾中所包含的 MoviesDBModel.edmx 檔案,以開啟實體設計工具。
圖 5 – ADO.NET 實體資料模型設計工具
例如,您可以使用實體設計工具來變更實體模型資料精靈所產生的類別名稱。 精靈建立了名為 Movies 的新資料存取類別。 換句話說,精靈會為類別提供與資料庫資料表完全相同的名稱。 由於我們將使用此類別來代表特定的 Movie 執行個體,因此我們應該將類別從 Movies 重新命名為 Movie。
如果您想要重新命名實體類別,您可以在實體設計工具中按兩下類別名稱,然後輸入新名稱 (參見圖 6)。 或者,您可以在選取 Entity Designer 中的實體之後,變更屬性視窗中實體的名稱。
圖 6 – 變更實體名稱
請記得按一下 [儲存] 按鈕儲存實體資料模型,方法是按一下 [儲存] 按鈕 (磁碟片圖示)。 在幕後,Entity Designer 會產生一組 C# 類別。 您可以從 [方案總管] 視窗開啟 MoviesDBModel.Designer.cs 檔案,以檢視這些類別。
請勿修改 Designer.cs 檔案中的程式碼,因為下次使用 Entity Designer 時會覆寫您的變更。 如果您想要擴充 Designer.cs 檔案中定義的實體類別功能,您可以在個別檔案中建立局部類別。
使用 Entity Framework 選取資料庫記錄
讓我們透過建立顯示電影記錄清單的頁面,開始建置影片資料庫應用程式。 清單 1 中的 Home 控制器公開名為 Index() 的動作。 Index() 動作利用 Entity Framework,從 Movie 資料庫資料表傳回所有電影記錄。
清單 1 – Controllers\HomeController.cs
using System.Linq;
using System.Web.Mvc;
using MovieEntityApp.Models;
namespace MovieEntityApp.Controllers
{
[HandleError]
public class HomeController : Controller
{
MoviesDBEntities _db;
public HomeController()
{
_db = new MoviesDBEntities();
}
public ActionResult Index()
{
ViewData.Model = _db.MovieSet.ToList();
return View();
}
}
}
請注意,清單 1 中的控制器包含建構函式。 建構函式會將具名 _db 的類別層級欄位初始化。 _db 欄位代表 Microsoft Entity Framework 所產生的資料庫實體。 _db 欄位是由 Entity Designer 產生的 MoviesDBEntities 類別執行個體。
若要在 Home 控制器中使用 MoviesDBEntities 類別,您必須匯入 MovieEntityApp.Models 命名空間 (MVCProjectName.Models)。
在 Index() 動作中使用 _db 欄位,從 Movies 資料庫資料表擷取記錄。 運算式 _db.MovieSet 代表 Movies 資料庫資料表中的所有記錄。 ToList() 方法可用來將電影集轉換成 Movie 物件的泛型集合 (List<Movie>)。
影片記錄會透過 LINQ to Entities 的協助擷取。 清單 1 中的 Index() 動作會使用 LINQ 方法語法來擷取資料庫記錄集。 如果您想要的話,可以改用 LINQ 查詢語法。 下列兩個陳述式執行極相同的動作:
ViewData.Model = _db.MovieSet.ToList();
ViewData.Model = (from m in _db.MovieSet select m).ToList();
使用您最直覺的 LINQ 語法 – 方法語法或查詢語法。 這兩種方法之間的效能沒有差異,唯一的差異是樣式。
清單 2 中的檢視是用來顯示電影記錄。
清單 2 – Views\Home\Index.aspx
<%@ Page Language="C#"
Inherits="System.Web.Mvc.ViewPage<List<MovieEntityApp.Models.Movie>>" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>Index</title>
</head>
<body>
<div>
<% foreach (var m in ViewData.Model)
{ %>
Title: <%= m.Title %>
<br />
Director: <%= m.Director %>
<br />
<%= Html.ActionLink("Edit", "Edit", new { id = m.Id })%>
<%= Html.ActionLink("Delete", "Delete", new { id = m.Id })%>
<hr />
<% } %>
<%= Html.ActionLink("Add Movie", "Add") %>
</div>
</body>
</html>
清單 2 中的檢視表包含 foreach 迴圈,逐一查看每筆電影記錄,並顯示電影記錄的 Title 和 Director 屬性的值。 請注意,每筆記錄旁邊顯示 [編輯和刪除] 連結。 此外,[新增電影] 連結出現在檢視表底部 (參見圖 7)。
圖 7 – 索引檢視
[索引] 檢視是具型別檢視表。 索引檢視包含 <%@ Page %> 指示詞,具有 Inherits 屬性,該屬性會將 Model 屬性轉換成 Movie 物件的強型別泛型清單集合 (List<Movie)。
使用 Entity Framework 插入資料庫記錄
您可以使用 Entity Framework 輕鬆地將新記錄插入資料庫資料表。 清單 3 包含新增至 Home 控制器類別的兩個新動作,您可用於將新記錄插入 Movie 資料庫資料表。
清單 3 – Controllers\HomeController.cs (Add 方法)
public ActionResult Add()
{
return View();
}
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Add(FormCollection form)
{
var movieToAdd = new Movie();
// Deserialize (Include white list!)
TryUpdateModel(movieToAdd, new string[] { "Title", "Director" }, form.ToValueProvider());
// Validate
if (String.IsNullOrEmpty(movieToAdd.Title))
ModelState.AddModelError("Title", "Title is required!");
if (String.IsNullOrEmpty(movieToAdd.Director))
ModelState.AddModelError("Director", "Director is required!");
// If valid, save movie to database
if (ModelState.IsValid)
{
_db.AddToMovieSet(movieToAdd);
_db.SaveChanges();
return RedirectToAction("Index");
}
// Otherwise, reshow form
return View(movieToAdd);
}
第一個 Add() 動作只傳回檢視表。 檢視表包含新增影片資料庫記錄的表單 (參見圖 8)。 當您提交表單時,會叫用第二個 Add() 動作。
請注意,第二個 Add() 動作是以 AcceptVerbs 屬性裝飾。 只有在執行 HTTP POST 作業時,才能叫用此動作。 換句話說,只有在張貼 HTML 表單時,才能叫用此動作。
第二個 Add() 動作會利用 ASP.NET MVC TryUpdateModel() 方法的協助,建立 Entity Framework Movie 類別的新執行個體。 TryUpdateModel() 方法會採用傳遞至 Add() 方法之 FormCollection 中的欄位,並將這些 HTML 表單欄位的值指派給 Movie 類別。
使用 Entity Framework 時,當您使用 TryUpdateModel 或 UpdateModel 方法更新實體類別的屬性時,必須提供屬性的「安全清單」。
接著,Add() 動作會執行一些簡單的表單驗證。 動作會驗證 Title 和 Director 屬性都含有值。 如果發生驗證錯誤,則會將驗證錯誤訊息新增至 ModelState。
如果沒有驗證錯誤,則會在 Entity Framework 的協助下,將新電影記錄加入至 Movies 資料庫資料表。 新的記錄會新增至資料庫,其中包含下列兩行程式碼:
_db.AddToMovieSet(movieToAdd);
_db.SaveChanges();
第一行程式碼會將新的 Movie 實體新增至 Entity Framework 追蹤的電影集。 第二行程式碼會儲存對追蹤回基本資料庫的 Movies 所做的任何變更。
圖 8 – 新增檢視
使用 Entity Framework 更新資料庫記錄
您可以遵照幾乎相同的方法,使用 Entity Framework 編輯資料庫記錄,就像剛遵照插入新資料庫記錄的方法一樣。 清單 4 包含兩個名為 Edit() 的新控制器動作。 第一個 Edit() 動作會傳回 HTML 表單來編輯電影記錄。 第二個 Edit() 動作會嘗試更新資料庫。
清單 4 – Controllers\HomeController.cs (Edit 方法)
public ActionResult Edit(int id)
{
// Get movie to update
var movieToUpdate = _db.MovieSet.First(m => m.Id == id);
ViewData.Model = movieToUpdate;
return View();
}
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Edit(FormCollection form)
{
// Get movie to update
var id = Int32.Parse(form["id"]);
var movieToUpdate = _db.MovieSet.First(m => m.Id == id);
// Deserialize (Include white list!)
TryUpdateModel(movieToUpdate, new string[] { "Title", "Director" }, form.ToValueProvider());
// Validate
if (String.IsNullOrEmpty(movieToUpdate.Title))
ModelState.AddModelError("Title", "Title is required!");
if (String.IsNullOrEmpty(movieToUpdate.Director))
ModelState.AddModelError("Director", "Director is required!");
// If valid, save movie to database
if (ModelState.IsValid)
{
_db.SaveChanges();
return RedirectToAction("Index");
}
// Otherwise, reshow form
return View(movieToUpdate);
}
第二個 Edit() 動作會從資料庫擷取符合所編輯電影識別碼的資料庫擷取電影記錄開始。 下列 LINQ to Entities 陳述式會擷取符合特定識別碼的第一筆資料庫記錄:
var movieToUpdate = _db.MovieSet.First(m => m.Id == id);
接著,TryUpdateModel() 方法可用來將 HTML 表單欄位值指派給電影實體的屬性。 請注意,會提供安全清單來指定要更新的確切屬性。
接著,會執行一些簡單的驗證,確認 Movie Title 和 Director 屬性都含有值。 如果任一屬性遺漏值,則會將驗證錯誤訊息新增至 ModelState,而 ModelState.IsValid 會傳回 false 值。
最後,如果沒有驗證錯誤,基礎 Movies 資料庫資料表會藉由呼叫 SaveChanges() 方法來更新任何變更。
編輯資料庫記錄時,您必須將正在編輯的記錄識別碼,傳遞至執行資料庫更新的控制器動作。 否則,控制器動作不會知道基礎資料庫中要更新的記錄。 清單 5 中包含的 [編輯] 檢視表包含隱藏的表單欄位,這代表正在編輯之資料庫記錄的識別碼。
清單 5 – Views\Home\Edit.aspx
<%@ Page Language="C#"
Inherits="System.Web.Mvc.ViewPage<MovieEntityApp.Models.Movie>" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>Edit</title>
<style type="text/css">
.input-validation-error
{
background-color:Yellow;
}
</style>
</head>
<body>
<div>
<h1>Edit Movie</h1>
<form method="post" action="/Home/Edit">
<!-- Include Hidden Id -->
<%= Html.Hidden("id") %>
Title:
<br />
<%= Html.TextBox("title") %>
<br /><br />
Director:
<br />
<%= Html.TextBox("director") %>
<br /><br />
<input type="submit" value="Edit Movie" />
</form>
</div>
</body>
</html>
使用 Entity Framework 刪除資料庫記錄
在此教學課程中,我們需要處理的最終資料庫作業,是刪除資料庫記錄。 您可以使用清單 6 中的控制器動作來刪除特定的資料庫記錄。
清單 6 -- \Controllers\HomeController.cs (刪除動作)
public ActionResult Delete(int id)
{
// Get movie to delete
var movieToDelete = _db.MovieSet.First(m => m.Id == id);
// Delete
_db.DeleteObject(movieToDelete);
_db.SaveChanges();
// Show Index view
return RedirectToAction("Index");
}
Delete() 動作會先擷取符合傳遞給動作之識別碼的 Movie 實體。 接著,會呼叫 DeleteObject() 方法從資料庫刪除電影,然後接著用 SaveChanges() 方法。 最後,使用者會重新導回 [索引] 檢視。
摘要
此教學課程的目的是,示範如何利用 ASP.NET MVC 和 Microsoft Entity Framework 來建置資料庫驅動的 Web 應用程式。 您已了解如何建置應用程式,讓您選取、插入、更新和刪除資料庫記錄。
首先,我們已討論如何使用實體資料模型精靈,從 Visual Studio 內產生實體資料模型。 接著,您會了解如何使用 LINQ to Entities 從資料庫資料表擷取一組資料庫記錄。 最後,我們使用 Entity Framework 插入、更新和刪除資料庫記錄。