在本节中,您将使用Entity Framework Code First来实现模型类上的操作。从而使得这些操作和变更,可以应用到数据库中。
默认情况下,就像您在之前的教程中所作的那样,使用 Entity Framework Code First自动创建一个数据库,Code First为数据库所添加的表,将帮助您跟踪数据库是否和从它生成的模型类是同步的。如果他们不是同步的,Entity Framework将抛出一个错误。这非常方便的在开发时就可以发现错误,否则您可能会在运行时才发现这个问题。 (由一个晦涩的错误信息,才发现这个问题。)
# 为对象模型的变更设置 Code First Migrations
如果您使用的是 Visual Studio 2012,从解决方案资源管理器中双击*Movies.mdf*,打开数据库工具。Visual Studio Express for Web将显示数据库资源管理器,Visual Studio 2012 将显示服务器资源管理器。如果您使用的是Visual Studio 2010,请使用 SQL Server对象资源管理器。
在数据库工具 (数据库资源管理器、 服务器资源管理器或 SQL Server对象资源管理器),右键单击`MovieDBContext`,并选择**删除**以删除电影数据库。
[![clip_image001](https://box.kancloud.cn/2016-08-08_57a81c68e71f2.png "clip_image001")
](http://images.cnitblog.com/blog/139239/201302/26103507-f4a4022445024feb9f665063eab77056.png)
返回到解决方案资源管理器。在Movies.mdf文件上右键单击,并选择**删除**以删除电影数据库。
[![clip_image002](https://box.kancloud.cn/2016-08-08_57a81c6906ad2.png "clip_image002")
](http://images.cnitblog.com/blog/139239/201302/26103509-105c719a0df44901973f03fffa49426d.png)
Build应用程序,以确保没有任何编译错误。
从**工具**菜单上,单击**库包管理器**,然后点击**程序包管理器控制台**.
[![clip_image003](https://box.kancloud.cn/2016-08-08_57a81c69235fa.png "clip_image003")
](http://images.cnitblog.com/blog/139239/201302/26103511-1cc4a1f86bb84645a363a6fa7c54dda1.png)
在 **软件包管理器控制台 **窗口中` `PM> 提示符下输入"Enable-Migrations –ContextTypeName MvcMovie.Models.MovieDBContext"。
[![clip_image004](https://box.kancloud.cn/2016-08-08_57a81c6940440.png "clip_image004")
](http://images.cnitblog.com/blog/139239/201302/26103514-780e6a5bb9e34d13812c59c7608dccad.png)
(如上所示)**Enable-Migrations**命令会在Migrations文件夹中创建一个Configuration.cs文件。
[![clip_image005](https://box.kancloud.cn/2016-08-08_57a81c69579e9.png "clip_image005")
](http://images.cnitblog.com/blog/139239/201302/26103516-a2bdbfbf31b24fe5a599069367446d16.png)
在Visual Studio 中打开Configuration.cs文件。把Configuration.cs文件中的Seed方法,替换为下面的代码:
~~~
protected override void Seed(MvcMovie.Models.MovieDBContext context) { context.Movies.AddOrUpdate( i => i.Title, new Movie { Title = "When Harry Met Sally", ReleaseDate = DateTime.Parse("1989-1-11"), Genre = "Romantic Comedy", Price = 7.99M }, new Movie { Title = "Ghostbusters ", ReleaseDate = DateTime.Parse("1984-3-13"), Genre = "Comedy", Price = 8.99M }, new Movie { Title = "Ghostbusters 2", ReleaseDate = DateTime.Parse("1986-2-23"), Genre = "Comedy", Price = 9.99M }, new Movie { Title = "Rio Bravo", ReleaseDate = DateTime.Parse("1959-4-15"), Genre = "Western", Price = 3.99M } ); }
~~~
在Movie下面出现的红色波浪线上右键单击,并选择**Resolve**然后点击**using MvcMovie.Models;**
[![clip_image006](https://box.kancloud.cn/2016-08-08_57a81c696bfc0.png "clip_image006")
](http://images.cnitblog.com/blog/139239/201302/26103519-5ac9cd6b8fb24ab0a215fe765c5cb608.png)
这样做之后,将添加以下的 using语句:
using MvcMovie.Models;
每次Code First Migrations 会调用Seed 方法(即,在程序包管理器控制台中调用**update-database**),并且此次调用会更新行:更新已经插入的行,或把不存在的行也插入。
**按 CTRL-SHIFT-B 来Build工程。**(如果此次Build不成功,以下的步骤将会失败。)
下一步是创建一个`DbMigration`类,用于初始化数据库迁移。此迁移类将创建新的数据库,这也就是为什么在之前的步骤中你要删除`movie.mdf`文件。
在**软件包管理器控制台**窗口中,输入"add-migration Initial"命令来创建初始迁移。" Initial" 的名称是任意,是用于创建迁移文件的名称。
[![clip_image007](https://box.kancloud.cn/2016-08-08_57a81c6985b9f.png "clip_image007")
](http://images.cnitblog.com/blog/139239/201302/26103522-26a4ea5c7dd04d57b0afa0718164af3c.png)
Code First Migrations将会在Migrations文件夹中创建另一个类文件 (文件名为:* {DateStamp}_Initial.cs* ),此类中包含的代码将创建数据库的Schema。迁移文件名使用时间戳作为前缀,以帮助用来排序和查找。查看*{DateStamp}_Initial.cs*文件,它包含了为电影数据库创建电影表的说明。当您更新数据库时,*{DateStamp}_Initial.cs*文件将会被运行并创建 DB 的Schema。然后**Seed**方法将运行,用来填充 DB 的测试数据。
在**软件包管理器控制台**中,输入命令" update-database ",创建数据库并运行**Seed**方法。
[![clip_image008](https://box.kancloud.cn/2016-08-08_57a81c699f142.png "clip_image008")
](http://images.cnitblog.com/blog/139239/201302/26103525-2c30bcf0187746648cbc801ae1f655ec.png)
如果您收到表已经存在并且无法创建的错误,可能是因为您已经删除了数据库,并且在执行`update-database`之前,您运行了应用程序。在这种情况下,再次删除Movies.mdf文件,然后重试`update-database`命令。如果您仍遇到错误,删除Migration文件夹及其内容,然后从头开始重做。(即删除Movies.mdf文件,然后再进行Enable-Migrations)
运行该应用程序,然后浏览URL /Movies Seed数据显示如下:
[![clip_image009](https://box.kancloud.cn/2016-08-08_57a81c69b4ec8.png "clip_image009")
](http://images.cnitblog.com/blog/139239/201302/26103527-dbe82fe3a3554a5185c4bd74bb567459.png)
# 为影片模型添加评级属性
给现有的`Movie`类,添加新的`Rating`属性。打开Models\Movie.cs文件并添加如下`Rating`属性:
public string Rating { get; set; }
完整的`Movie`类如下:
~~~
public class Movie { public int ID { get; set; } public string Title { get; set; } public DateTime ReleaseDate { get; set; } public string Genre { get; set; } public decimal Price { get; set; } public string Rating { get; set; } }
~~~
Build 应用程序 **Build**>**Build Move**或CTRL-SHIFT-B.
现在,您已经更新了`Model`类,您还需要更新*\Views\Movies\Index.cshtml*和*\Views\Movies\Create.cshtml*视图模板,以便能在浏览器中显示新的`Rating`属性。
打开*\Views\Movies\Index.cshtml*文件,在**Price**列后面添加`<th>Rating</th>`的列头。然后添加一个`<td>`列来显示`@item.Rating`的值。下面是更新的*Index.cshtml*视图模板:
@model IEnumerable<MvcMovie.Models.Movie> @{ ViewBag.Title = "Index"; } <h2>Index</h2> <p> @Html.ActionLink("Create New", "Create") </p> <table> <tr> <th> @Html.DisplayNameFor(model => model.Title) </th> <th> @Html.DisplayNameFor(model => model.ReleaseDate) </th> <th> @Html.DisplayNameFor(model => model.Genre) </th> <th> @Html.DisplayNameFor(model => model.Price) </th> <th> @Html.DisplayNameFor(model => model.Rating) </th> <th></th> </tr> @foreach (var item in Model) { <tr> <td> @Html.DisplayFor(modelItem => item.Title) </td> <td> @Html.DisplayFor(modelItem => item.ReleaseDate) </td> <td> @Html.DisplayFor(modelItem => item.Genre) </td> <td> @Html.DisplayFor(modelItem => item.Price) </td> <td> @Html.DisplayFor(modelItem => item.Rating) </td> <td> @Html.ActionLink("Edit", "Edit", new { id=item.ID }) | @Html.ActionLink("Details", "Details", new { id=item.ID }) | @Html.ActionLink("Delete", "Delete", new { id=item.ID }) </td> </tr> } </table>
下一步,打开*\Views\Movies\Create.cshtml*文件,并在form标签结束处的附近添加如下代码。您可以在创建新的电影时指定一个电影等级。
<div class="editor-label"> @Html.LabelFor(model => model.Rating) </div> <div class="editor-field"> @Html.EditorFor(model => model.Rating) @Html.ValidationMessageFor(model => model.Rating) </div>
现在,您已经更新应用程序代码以支持了新的`Rating`属性。
现在运行该应用程序,然后浏览 */Movies*的 URL。然而,当您这样做时,您将看到以下之一的错误信息:
[![clip_image010](https://box.kancloud.cn/2016-08-08_57a81c69d662d.png "clip_image010")
](http://images.cnitblog.com/blog/139239/201302/26103530-144e249e876d4abbb9471c10ea08a6c6.png)
[![clip_image011](https://box.kancloud.cn/2016-08-08_57a81c69f0e89.png "clip_image011")
](http://images.cnitblog.com/blog/139239/201302/26103533-728a67e5188345ec839af454afde15a1.png)
你现在看到此错误,因为在应用程序中,最新的`Movie`模型类和现有的数据库`Movie`表的Schema不同。(数据库表中,没有`Rating`列。)
我们将使用Code First Migrations 来解决这一问题。
更新Seed方法,以便它能为新的列提供一个值。打开 Migrations\Configuration.cs 文件,并将Rating 字段添加到影片的每个对象。
~~~
new Movie
{
Title = "When Harry Met Sally",
ReleaseDate = DateTime.Parse("1989-1-11"),
Genre = "Romantic Comedy",
Rating = "G",
Price = 7.99M
},
~~~
Build解决方案,然后打开 **软件包管理器控制台 **窗口,并输入以下命令:
`add-migration AddRatingMig`
`add-migration`命令告诉migration framework,来检查当前电影模型与当前的影片 DB Schema并创建必要的代码以将数据库迁移到新的模型。AddRatingMig 是一个任意的文件名参数,用于命名migration文件。它将有助于使得迁移步骤成为一个有意义的名字。
当命令完成后,用Visual Studio 打开类文件,新继承自`DbMIgration` 类的定义,并在`Up` 方法中,您可以看到创建新列的代码:
public partial class AddRatingMig : DbMigration{ public override void Up() { AddColumn("dbo.Movies", "Rating", c => c.String()); } public override void Down() { DropColumn("dbo.Movies", "Rating"); }}
Build解决方案,然后在 **程序包管理器控制台 **窗口中输入"update-database"命令。
下面的图片显示了 **程序包管理器控制台 **窗口的输出 (AddRatingMig 的前缀时间戳将有所不同)。
[![clip_image012](https://box.kancloud.cn/2016-08-08_57a81c6a1a111.png "clip_image012")
](http://images.cnitblog.com/blog/139239/201302/26103536-fe402381df9040cdabb2f019681f3bfd.png)
重新运行应用程序,然后浏览 /Movies 的 URL。您可以看到新的评级字段。
[![clip_image013](https://box.kancloud.cn/2016-08-08_57a81c6a32750.png "clip_image013")
](http://images.cnitblog.com/blog/139239/201302/26103542-1394ea9741a44c97a561e2186d102a34.png)
单击**CreateNew**链接来添加一部新电影。注意,请您可以为电影添加评级。
[![clip_image014](https://box.kancloud.cn/2016-08-08_57a81c6a543b0.png "clip_image014")
](http://images.cnitblog.com/blog/139239/201302/26103545-89ff632688d0460d911d756c5ee59df4.png)
单击**Create**。新的电影,包括评级,将显示在电影列表中:
[![clip_image015](https://box.kancloud.cn/2016-08-08_57a81c6a6e792.png "clip_image015")
](http://images.cnitblog.com/blog/139239/201302/26103547-3c946779d5eb4cd48b14ea59dad39148.png)
此外您也应该把`Rating` 字段添加到编辑、 详细信息和 SearchIndex 的视图模板中。
您可以再次在 **程序包管理器控制台 **窗口中输入"update-database"命令,将不会有任何新的变化,因为数据库Schema 和模型类现在是匹配的。
在本节中,您看到了如何修改模型对象并始终保持其和数据库Schema的同步。您还学习了使用填充示例数据来创建新数据库的例子,您可以反复尝试。接下来,让我们看看如何将丰富的验证逻辑添加到模型类,并对模型类执行一些强制的业务规则验证。
--------------------------------------------------------------------------------------------------------------------
译者注:
本系列共9篇文章,翻译自Asp.Net MVC4 官方教程,由于本系列文章言简意赅,篇幅适中,从一个示例开始讲解,全文最终完成了一个管理影片的小系统,非常适合新手入门Asp.Net MVC4,并由此开始开发工作。9篇文章为:
1. Asp.Net MVC4 入门介绍
· 原文地址:[http://www.asp.net/mvc/tutorials/mvc-4/getting-started-with-aspnet-mvc4/intro-to-aspnet-mvc-4](http://www.asp.net/mvc/tutorials/mvc-4/getting-started-with-aspnet-mvc4/intro-to-aspnet-mvc-4)
· 译文地址:[http://www.cnblogs.com/powertoolsteam/archive/2012/11/01/2749906.html](http://www.cnblogs.com/powertoolsteam/archive/2012/11/01/2749906.html)
2. 添加一个控制器
· 原文地址:[http://www.asp.net/mvc/tutorials/mvc-4/getting-started-with-aspnet-mvc4/adding-a-controller](http://www.asp.net/mvc/tutorials/mvc-4/getting-started-with-aspnet-mvc4/adding-a-controller)
· 译文地址:[http://www.cnblogs.com/powertoolsteam/archive/2012/11/02/2751015.html](http://www.cnblogs.com/powertoolsteam/archive/2012/11/02/2751015.html)
3. 添加一个视图
· 原文地址:[http://www.asp.net/mvc/tutorials/mvc-4/getting-started-with-aspnet-mvc4/adding-a-view](http://www.asp.net/mvc/tutorials/mvc-4/getting-started-with-aspnet-mvc4/adding-a-view)
· 译文地址:[http://www.cnblogs.com/powertoolsteam/archive/2012/11/06/2756711.html](http://www.cnblogs.com/powertoolsteam/archive/2012/11/06/2756711.html)
4. 添加一个模型
· 原文地址:[http://www.asp.net/mvc/tutorials/mvc-4/getting-started-with-aspnet-mvc4/adding-a-model](http://www.asp.net/mvc/tutorials/mvc-4/getting-started-with-aspnet-mvc4/adding-a-model)
· 译文地址:[http://www.cnblogs.com/powertoolsteam/archive/2012/12/17/2821495.html](http://www.cnblogs.com/powertoolsteam/archive/2012/12/17/2821495.html)
5. 从控制器访问数据模型
· 原文地址:[http://www.asp.net/mvc/tutorials/mvc-4/getting-started-with-aspnet-mvc4/accessing-your-models-data-from-a-controller](http://www.asp.net/mvc/tutorials/mvc-4/getting-started-with-aspnet-mvc4/accessing-your-models-data-from-a-controller)
· 译文地址:[http://www.cnblogs.com/powertoolsteam/archive/2013/01/11/2855935.html](http://www.cnblogs.com/powertoolsteam/archive/2013/01/11/2855935.html)
6. 验证编辑方法和编辑视图
· 原文地址:[http://www.asp.net/mvc/tutorials/mvc-4/getting-started-with-aspnet-mvc4/examining-the-edit-methods-and-edit-view](http://www.asp.net/mvc/tutorials/mvc-4/getting-started-with-aspnet-mvc4/examining-the-edit-methods-and-edit-view)
· 译文地址:[http://www.cnblogs.com/powertoolsteam/archive/2013/01/24/2874622.html](http://www.cnblogs.com/powertoolsteam/archive/2013/01/24/2874622.html)
7. 给电影表和模型添加新字段
· 原文地址:[http://www.asp.net/mvc/tutorials/mvc-4/getting-started-with-aspnet-mvc4/adding-a-new-field-to-the-movie-model-and-table](http://www.asp.net/mvc/tutorials/mvc-4/getting-started-with-aspnet-mvc4/adding-a-new-field-to-the-movie-model-and-table)
· 译文地址:[http://www.cnblogs.com/powertoolsteam/archive/2013/02/26/2933105.html](http://www.cnblogs.com/powertoolsteam/archive/2013/02/26/2933105.html)
8. 给数据模型添加校验器
· 原文地址:[http://www.asp.net/mvc/tutorials/mvc-4/getting-started-with-aspnet-mvc4/adding-validation-to-the-model](http://www.asp.net/mvc/tutorials/mvc-4/getting-started-with-aspnet-mvc4/adding-validation-to-the-model)
· 译文地址:
9. 查询详细信息和删除记录
· 原文地址:[http://www.asp.net/mvc/tutorials/mvc-4/getting-started-with-aspnet-mvc4/examining-the-details-and-delete-methods](http://www.asp.net/mvc/tutorials/mvc-4/getting-started-with-aspnet-mvc4/examining-the-details-and-delete-methods)
· 译文地址:
- 前言
- 入门介绍
- 添加一个控制器
- 添加一个视图
- 添加一个模型
- 从控制器访问数据模型
- 验证编辑方法和编辑视图
- 给电影表和模型添加新字段
- 给数据模型添加校验器
- 查询详细信息和删除记录
- 第三方控件Studio for ASP.NET Wijmo MVC4 工具应用
- ASP.NET MVC 5-开始MVC5之旅
- 控制器
- 视图
- 将数据从控制器传递给视图
- 添加一个模型
- 创建连接字符串(Connection String)并使用SQL Server LocalDB
- 从控制器访问数据模型
- 验证编辑方法(Edit method)和编辑视图(Edit view)
- 给电影表和模型添加新字段
- 给数据模型添加校验器
- 查询Details和Delete方法