[翻译]使用Entity Framework创建模型类
本文章为原创翻译文章,提供源代码下载:/Files/sansi/Movies.rar
本教程的目标是说明当创建ASP.NET MVC应用程序时如使用Microsoft Entity Framework创建数据访问类。本教程假设你不知道Microsoft Entity Framework。在教程的最后,你会明白如何使用Entity Framework执行select, insert, update和delete数据库记录。
Microsoft Entity Framework是允许你从数据库自动生成数据访问层的对象关系映射工具。Entity Framework使避免创建数据访问类时沉闷的手工工作成为可能。
为了说明在ASP.NET MVC中如何使用Microsoft Entity Framework,我们来创建一个简单的例子。我们创建Movie数据库应用程序来显示、编辑Movie数据库记录。
本教程假设你已安装Visual Studio 2008 或 Visual Web Developer 2008 with Service Pack 1。为了使用Entity Framework你需要Service Pack 1。可以在http://www.asp.net/downloads/下载Visual Studio 2008 Service Pack 1 or Visual Web Developer with Service Pack 1。
ASP.NET MVC和Microsoft Entity Framework之间没有必要的联系。使用ASP.NETMVC时好几种能替代Entity Framework的方法。例如,你可以使用其它的O/RM工具如Microsoft LINQ to SQL, NHibernate, or SubSonic。
一、创建Movie示例数据库
Movie数据应用程序使用数据表Movies,包含以下列:
列名 |
数据类型 |
允许为空? |
是否主健? |
Id |
int |
FALSE |
TRUE |
Title |
nvarchar(100) |
FALSE |
FALSE |
Director |
nvarchar(100) |
FALSE |
FALSE |
依照下面的步骤将这个表加到ASP.NET MVC Project:
- 在解决方案资源管理器面板中右击App_Data文件夹,选择菜单“添加”,“新建项”。
- 在“添加新项”对话框,选择SQL Server Database,给数据库命名为MoviesDB.mdf,单击“添加”按钮。
- 双击MoviesDB.mdf文件打开服务器资源管理器。
- 展开MoviesDB.mdf数据库连接,右击数据表文件夹,选择新增数据表。
- 在数据表设计中,增加Id,Title和Director列。
- 单击保存按钮保存数据表为Movies。
创建完Movies数据表之后,需要往数据中添加一些示例数据。右击Movies表,选择菜单显示表数据。你可以加一些假数据到表格中。
二、创建ADO.NET Entity Data Model
为了使用Entity Framework,你需要创建一个实体数据模型。你可以使用Visual Studio Entity Data Model Wizard自动从数据库创建实体数据模型。
依照下面的步骤:
- 右击解决方案管理器中的Models文件夹,选择添加,新建项。
- 在新建项对话框中,选择数据类别(参见Figure 1)。
- 选择ADO.NET Entity DataModel模板,命名为MoviesDBModel.edmx,再单击添加按钮。单击添加按钮启动数据模型向导。
- 在选择模型内容步骤里,选择从数据库生成选择,然后单击下一步按钮(参见Figure2)。
- 在选择数据连接步骤,选择MoviesDB.mdf数据连接,输入实体连接设置名称为MoviesDBEntities,然后单击下一步按钮(参见Figure 3)。
- 在选择数据对象步骤,选择Movie数据表,单击完成按钮(参见Figure4)。
完成这些步骤后,打开ADO.NET Entity Data Model 设计器。
Figure 1 – 创建新的 Entity Data Model
Figure 2 – 选择Model Contents Step
Figure 3 – 选择数据连接
Figure 4 – 选择数据对象
三、修改ADO.NET Entity Data Model
创建完实体数据模型之后,你可以修通过实体设计器修改模型(参见Figure5)。你可以在任何时间通过双击解决方案资源管理器下Models文件夹下的MoviesDBModel.edmx打开实体设计器。
Figure 5 – ADO.NET Entity Data Model 设计器
例如,你可以使用实体设计器修改Entity Model Data 向导生成的类名。向导创建了名为Movies的数据访问类。换句话说,向导给类命名为数据表名。因为我们将使用这个类显示特定的Movies实例,我们应该重命名这个类Movies为Movie。
如果你想重命名实体类,你可以在实体设计器中双击类名,然后输入一个新名称(参见Figure6)。或者,你可以在实体设计器中选择一个实体后在属性窗口修改实体名。
Figure 6 – 修改实体名称
做了修改之后,记得通过单击保存按钮保存Entity Data Model。实体设计器在幕后生成一系列C#类。你可以通过打开解决方案资源管理器中的MoviesDBModel.Designer.cs文件查看这些类。
不要直接修改Designer.cs文件中的代码,因为下次使用实体设计器时你的修改会被覆盖。如果你想扩展Designer.cs实体类中的功能,你可以在单独的文件中创建partial classes。
四、使用Entity Framework查询数据记录
让我们通过创建一张显示movie记录的页面开始建我们的movie数据应用程序。List1中的Home controller有一个名为Index()的action。Index() action使用Entity Framework从Movie数据库返回所有的movie记录。
Listing 1 – Controllers\HomeController.cs
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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();
}
}
}
注意Listing 1中的controller包含一个构造函数。构造函数初始化了一个类级别的字段_db。_db字段表示通过Microsoft Entity Framework生成的数据实体。_db字段是通过实体设计器生成的MvoiesDBEntities类的实例。
为了使用Home controller中的MoviesDBEntities类,你必须添加MovieEntityApp.Models命名空间(MVCProjectName.Models)。
_db字段使用在Index() action中,用于从Movies数据表获取记录。表达式_db.MovieSet代表了Movies数据表中的所有记录。ToList()方法用于把Movies数据集转换成Movie对象集合(List<Movie>)。
Movie记录都是在LINQ to Entities帮助获取到的。Listing 1中的Index() action使用LINQ语法获取数据记录集。如果你喜欢,你也可以使用LINQ查询语法。下面两个语句做的是同样的事情:
ViewData.Model = _db.MovieSet.ToList();
ViewData.Model = (from m in _db.MovieSet select m).ToList();
你会发现无论是使用LINQ的方法语法或查询语法都非常直观。这两种方法的执意是相同的,只是书写方式不同。
Listing 2中的View用于显示movie记录。
Listing 2 – Views\Home\Index.aspx
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<!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>
Listing 2中的View包含一个foreach循环,它循环访问每一条movie记录并显示它的Title和Director属性。注意每一条记录旁显示“编辑”和“删除”链接。此外,在视图的底部有“添加电影”的链接。
Figure 7 – The Index view
Index 视图是类型化了的视图。Index视图包括<%@ Page %>指令,它的属性Inherits表明模型为Movie对象强类型泛型列表集合(List<Movie>)。
五、使用Entity Framework插入数据记录
你可以使用Entity Framework轻松插入数据到数据库。Listing 3 包含两个新加入到Home controller类的action,它们用来插入新记录到Movie数据库。
Listing 3 – Controllers\HomeController.cs (Add methods)
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
{
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() action只是返回一个视图。视图包含一个用于添加movie数据库记录的表单(参见Figure8)。当你提交表单的时候,第二个Add() action被调用。
注意第二个Add() action上有AcceptVerbs属性。这个action只有在执行HTTP POST的时候被调用。换句话说,这个action只有在post一个HTML表单的时候调用。
第二个Add() action在ASP.NET MVC TryUpdateModel()方法的帮助下创建一个Entity Framework Movie 类的实例。TryUpdateModel()方法获取传给Add()方法的FormCollection的字段,并赋值这些HTML form字段的值给movie类。
使用实体构架时,在使用TryUpdateModel或UpdateModel方法更新实体类的属性时,你必须提供属性的“白名单”。
接下来,Add() action执行简单的表单检查。Action核实Title和Director属性都必须有值。如果验证出错误,验证错误信息会被加到ModelState中。
如果没有验证错误,一条movie记录就在实体框架的帮助下被加到了Movies数据表。新记录通过来下两行代码被加到数据库:
_db.AddToMovieSet(movieToAdd);
_db.SaveChanges();
第一行代码增加新的Movie实体到被实体框架追踪的movies数据集。第二行代码保存对Movies做出的修改。
Figure 8 – The Add view
六、使用Entity Framework更新数据记录
你可以按照几乎跟刚才使用实体框架进行新增记录相同的途径修改一条数据库记录。Listing 4包含两个新的名为Edit()的controller action。第一个Edit() action返回用于修改movie记录的表单。第二个Edit() action试图更新数据库。
Listing 4 – Controllers\HomeController.cs (修改 methods)
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
{
// 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() action 根据Id从数据库获取与之相匹配的记录。下面的LINQ to Entities语句获取到与Id相匹配的第一条记录:
var movieToUpdate = _db.MovieSet.First(m => m.Id == id);
接下来,TryUpdateModel()方法用于将HTML表单中的字段赋值到movie实体。注意白名单用来指定需要修改的属性。
再接下来,又是针对Title和Director的一些简单的验证。如果哪一个属性值没有填写,就会出现错误信息,并被加到ModelState,同时ModelState.IsValid值返回false值。
最后,如果没有验证错误,Movies数据表就会通过SaveChanges()方法被修改。
在修改数据库记录时,你需要传递需要被的记录的Id值到controller action执行数据库更新。否则,controller action将不知道哪一条记录要被更新。在Edit视图,在Listing 5中,包含了一个隐藏的表单字段,它存储了记录的Id值。
Listing 5 – Views\Home\Edit.aspx
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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删除数据记录
这个教程的最后一个数据库操作是删除数据库记录。你可以使用Listing 6中的controller action删除一条特定的数据记录。
Listing 6 -- \Controllers\HomeController.cs (Delete action)
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() action首先通过传递进来的参数Id获取与之匹配的Movie实体。接下来,通过调用DeleteObject()方法和SaveChanges()方法删除此条记录。最后跳转到Index视图。
小结
这个教程的目的是示范如何使用ASP.NET MVC和Microsoft Entity Framework创建数据库驱动的Web应用程序。你会学习到如何创建一个允许你Select, insert, update和delete数据库记录的应用程序。
首先,我们讨论了如何使用实体数据模型向导在Visual Studio生成实体数据模型。接下来,你学习到了如何使用LINQ to Entities从数据库检索数据记录。最后,我们使用实体框架对数据记录进行Insert, update, delete操作。
本博客已不再更新,欢迎访问新地址