在本节中,我们将使用Entity Framework Code First 数据迁移功能将模型类的改变应用到数据库中。 默认情况下,当我们使用Entity Framework Code First 自动创建一个数据库,像我们之前教程中讲的那样,Code First 添加一个table帮我们跟踪数据库结构是否与模型类同步。如果不同步,Entity Framework 将抛出一个错误,这样更方便我们在开发的时候发现问题,否则只能在运行时通过晦涩的错误来查找了。 为模型更改设置 Code First 数据迁移在解决方案资源管理器中,删除自动创建的 Movies.mdf 文件。 在工具菜单中,选择“库程序包管理器”>“程序包管理器控制台”: 图1:打开“程序包管理器控制台”菜单项 在“程序包管理器控制台”窗口中输入:Enable-Migrations -ContextTypeName MvcMovie.Models.MovieDBContext 图2:运行命令 Enable-Migrations 命令创建了一个Migrations文件夹和Configuration.cs文件。 图3:新添加的文件 打开 Configuration.cs 文件,使用以下代码替换 Seed 方法: 代码清单1:Seed 方法 - Configruation.cs 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 } ); } 使用这段代码的时候,需要添加 using MvcMovie.Models 的引用。 Code First 数据迁移在每次迁移(在程序包管理器控制台中调用 update-database)的时候都会调用Seed方法。 在进行下一步之前,先编译解决方案,否则下一步会出错误。 下一步,为初始化迁移创建一个 DbMigration 类。这次迁移创建一个新数据库,这也是我们为什么要删除之前的数据库的原因。 在“程序包管理器控制台”窗口,输入命令 图4:创建初始化迁移 Code First Migrations 创建在Migrations文件夹中创建了一个文件(文件名是 {DateStamp}_Initial.cs ),这个类包含了创建数据库结构的代码。迁移文件的文件名以DateStamp开头是为了更好的排序,打开 {DateStamp}_Initial.cs 文件,它包含了为数据库MovieDB创建Movies表的指令。当你使用下面的命令更新数据库时,{DateStamp}_Initial.cs 文件将会运行并创建数据库结构,然后将执行 Seed 方法将测试数据插入数据库中。 在“程序包管理器控制台”中输入命令 图5:执行更新数据库命令 运行应用程序,浏览/Movies 地址,我们在Seed方法中添加的数据如下: 图6:浏览程序 为Movie模型添加Rating字段上面的内容一直在介绍如何进行数据迁移,现在开始为Movie类添加Rating字段,打开Movie.cs 文件,为它添加一个Rating字段,添加后的代码如下: 代码清单2:添加Rating字段后的Movie类 public class Movie { public int ID { get; set; } public string Title { get; set; } [Display(Name = "Release Date")] [DataType(DataType.Date)] public DateTime ReleaseDate { get; set; } public string Genre { get; set; } public decimal Price { get; set; } public string Rating { get; set ; }
}
编译解决方案。 现在我们已经更新了Movie类,你还需要修改\Views\Movies\Index.cshtml 和 \Views\Movies\Create.cshtml 视图。修改后的代码如下: 代码清单3:修改后的Index.cshtml @model IEnumerable<MvcMovie.Models.Movie> @{ ViewBag.Title = "Index"; } <h2>Index</h2> <p> @Html.ActionLink("Create New", "Create") </p> @using (Html.BeginForm("Index", "Movies", FormMethod.Get)) { <p> Genre: @Html.DropDownList("movieGenre", "All") Title: @Html.TextBox("SearchString") <br /> <input type="submit" value="Filter" /> </p> } <table class="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> 代码清单3:修改后的Create.cshtml @model MvcMovie.Models.Movie @{ ViewBag.Title = "Create"; } <h2>Create</h2> @using (Html.BeginForm()) { @Html.AntiForgeryToken() @Html.ValidationSummary(true) <fieldset class="form-horizontal"> <legend>Movie</legend> <div class="control-group"> @Html.LabelFor(model => model.Title, new { @class = "control-label" }) <div class="controls"> @Html.EditorFor(model => model.Title) @Html.ValidationMessageFor(model => model.Title, null, new { @class = "help-inline" }) </div> </div> <div class="control-group"> @Html.LabelFor(model => model.ReleaseDate, new { @class = "control-label" }) <div class="controls"> @Html.EditorFor(model => model.ReleaseDate) @Html.ValidationMessageFor(model => model.ReleaseDate, null, new { @class = "help-inline" }) </div> </div> <div class="control-group"> @Html.LabelFor(model => model.Genre, new { @class = "control-label" }) <div class="controls"> @Html.EditorFor(model => model.Genre) @Html.ValidationMessageFor(model => model.Genre, null, new { @class = "help-inline" }) </div> </div> <div class="control-group"> @Html.LabelFor(model => model.Price, new { @class = "control-label" }) <div class="controls"> @Html.EditorFor(model => model.Price) @Html.ValidationMessageFor(model => model.Price, null, new { @class = "help-inline" }) </div> </div> < div class="control-group"> @Html.LabelFor(model => model.Rating, new { @class = "control-label" }) <div class="controls"> @Html.EditorFor(model => model.Rating) @Html.ValidationMessageFor(model => model.Rating, null, new { @class = "help-inline" }) </div> </div > <div class="form-actions no-color"> <input type="submit" value="Create" class="btn" /> </div> </fieldset> } <div> @Html.ActionLink("Back to List", "Index") </div> @section Scripts { @Scripts.Render("~/bundles/jqueryval") } 现在我们已经在程序中为Rating字段做成了修改。再次运行程序,浏览/movies 地址,这时我们会得到一个错误: 图7:错误页面 出现这个错误的原因是Movie模型类发生了变化,而与它对应的数据表 Movie 中并不存在Rating字段。 There are a few approaches to resolving the error: 解决这个问题有以下几种途径:
在本教程中,我们使用Code First 迁移。 更新Seed 方法,使它为Rating字段提供一个值。打开 Migrations\Configuration.cs 文件,为每一个Movie对象的Rating字段赋值。 代码清单4:修改后的Seek方法 protected override void Seed(MvcMovie.Models.MovieDBContext context) { context.Movies.AddOrUpdate(i => i.Title, new Movie { Title = "龙门飞甲", ReleaseDate = DateTime.Parse("2012-1-11"), Genre = "动作", Price = 30M, Rating = "优" }, new Movie { Title = "冰河世纪", ReleaseDate = DateTime.Parse("2011-3-1"), Genre = "动漫", Price = 65M, Rating = "良" }, new Movie { Title = "中国合伙人", ReleaseDate = DateTime.Parse("2013-6-18"), Genre = "励志", Price = 70M, Rating = "良" } ); } 重新编译解决方案,然后打开“程序包管理器控制台”,执行命令:add-migration Rating add-migration 命令告诉迁移程序去检查当前的Movie模型与当前数据库之间的差异,创建迁移数据库到最新模型的代码。名称 Rating 是可以随便命名的,此处用来命名迁移文件。 当命令执行完成之后,Visual Studio 会打开刚刚添加的继承自 DbMigration 的类文件,文件中有两个方法 Up和Down,分别用来升级和降级数据库。在Up方法中我们可以看到为数据库添加列的代码,而Down方法中的代码则是删除Rating列。 代码清单5:Rating类 public partial class Rating : DbMigration { public override void Up() { AddColumn("dbo.Movies", "Rating", c => c.String()); } public override void Down() { DropColumn("dbo.Movies", "Rating"); } } 编译解决方案,然后执行命令 图8:更新数据库 刷新我们出错的页面,你能看到已经加入了Rating字段: 图9:加入了Rating字段的界面 点击“Create New”链接试着添加一个电影信息,不要忘记为Rating字段赋值。 图10:新增页面 输入完成之后点击“Create”按钮,保存电影信息。 图11:保存后的列表
你还需要在Edit、Details和Delete视图中添加Rating字段。 如果你再次执行 "update-database" 命令,将不会做出任何修改,因为数据库结构和模型的结构已经相同了。 现在,通过项目中使用数据迁移,我们在添加字段或更新模型结构的时候不用再删除数据库了。在下一节中,我们将对结构做出更多的更改,并使用数据迁移来更新数据库。 本文同时发布在起飞网,原文地址:http://www./mvc/mvc-5-adding-a-new-field |
|
来自: 贾朋亮博客 > 《ASP.NET MVC 5 学习教程》