在本节中,您将使用Entity Framework Code First来实现模型类上的操作。从而使得这些操作和变更,可以应用到数据库中。

默认情况下,就像您在之前的教程中所作的那样,使用 Entity Framework Code First自动创建一个数据库,Code First为数据库所添加的表,将帮助您跟踪数据库是否和从它生成的模型类是同步的。如果他们不是同步的,Entity Framework将抛出一个错误。这非常方便的在开发时就可以发现错误,否则您可能会在运行时才发现这个问题。

为对象模型的变更设置 Code First Migrations

从解决方案资源管理器中双击Movies.mdf,打开数据库工具, 在数据库工具 (数据库资源管理器、 服务器资源管理器或 SQL Server对象资源管理器),右键单击Movies.mdf,并选择删除

ASP.NET MVC 5 - 给电影表和模型添加新字段_第1张图片

Build应用程序,以确保没有任何编译错误。

工具菜单上,单击库包管理器,然后点击程序包管理器控制台.

ASP.NET MVC 5 - 给电影表和模型添加新字段_第2张图片

程序包管理器控制台窗口,在提示符 PM> 后输入:

Enable-Migrations -ContextTypeName MvcMovie.Models.MovieDBContext

ASP.NET MVC 5 - 给电影表和模型添加新字段_第3张图片

如上所示的Enable-Migrations 命令,会在Migrations文件夹下创建一个Configuration.cs 文件。

ASP.NET MVC 5 - 给电影表和模型添加新字段_第4张图片

在Visual Studio 里面打开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)”,然后单击“usingMvcMovie.Models;

ASP.NET MVC 5 - 给电影表和模型添加新字段_第5张图片

这样做会增加下面的语句:

using MvcMovie.Models;

Code First Migrations调用Seed的方法,每个迁移(程序包管理器控制台更新数据库),此方法用于updates数据(如果数据存在),或inserted数据。

在AddOrUpdate方法在下面的代码执行一个的“upsert”操作:

context.Movies.AddOrUpdate(i => i.Title,   
    new Movie    
    {    
        Title = "When Harry Met Sally",    
        ReleaseDate = DateTime.Parse("1989-1-11"),    
        Genre = "Romantic Comedy",    
        Rating = "PG",    
        Price = 7.99M    
    }

因为Seed方法与每个迁移同时运行时,故,你不能仅仅插入数据,因为当你正试图添加,可能已经完成了创建数据库后的第一次迁移。“upsert”操作阻止错误的发生,如果你尝试插入一个已经存在的行,它覆盖任何数据更改,当你在测试应用程序的同时。你可能不希望这样的事情发生:在某些情况下,当您更改数据测试时,你希望你的变化后数据库同步更新。在这种情况下,你想要做一个有条件的插入操作:只有当它不存在的时候,插入一行。    
传递给AddOrUpdate的方法的第一个参数, 指定的属性来使用以检查是否已存在某行。对于您所提供的测试影片的数据,Title属性可以被用于此目的,因为每个标题在列表中是唯一:

context.Movies.AddOrUpdate(i => i.Title,

这个代码假设titiles属性是唯一的。如果手动添加一个重复的标题,你会得到下面的异常。    
Sequence contains more than one element
更多关于 AddOrUpdate 方法的信息,请参见 Take care with EF 4.3 AddOrUpdate Method..

CTRL-SHIFT-B Build工程。(如果此次Build不成功,以下的步骤将会失败。)

下一步是创建一个DbMigration类,用于初始化数据库迁移。此迁移类将创建新的数据库,这也就是为什么在之前的步骤中你要删除movie.mdf文件。

软件包管理器控制台窗口中,输入"add-migration Initial"命令来创建初始迁移。" Initial" 的名称是任意,是用于创建迁移文件的名称。

ASP.NET MVC 5 - 给电影表和模型添加新字段_第6张图片

Code First Migrations将会在Migrations文件夹中创建另一个类文件 (文件名为: {DateStamp}_Initial.cs ),此类中包含的代码将创建数据库的Schema。迁移文件名使用时间戳作为前缀,以帮助用来排序和查找。查看{DateStamp}_Initial.cs文件,它包含了为电影数据库创建电影表的说明。当您更新数据库时, {DateStamp}_Initial.cs文件将会被运行并创建 DB 的Schema。然后Seed方法将运行,用来填充 DB 的测试数据。

软件包管理器控制台中,输入命令" update-database ",创建数据库并运行Seed方法。

ASP.NET MVC 5 - 给电影表和模型添加新字段_第7张图片

如果您收到表已经存在并且无法创建的错误,可能是因为您已经删除了数据库,并且在执行update-database之前,您运行了应用程序。在这种情况下,再次删除Movies.mdf文件,然后重试update-database命令。如果您仍遇到错误,删除Migration文件夹及其内容,然后从头开始重做。(即删除Movies.mdf文件,然后再进行Enable-Migrations)

运行该应用程序,然后浏览URL /Movies Seed数据显示如下:

ASP.NET MVC 5 - 给电影表和模型添加新字段_第8张图片

为影片模型添加评级(Rating)属性

给现有的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; }
    [Display(Name = "Release Date")]   
    [DataType(DataType.Date)]    
    [DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)]    
    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.

因为你已经添加了新的字段,电影类的,你还需要Bind,所以这次新的属性将被包含。更新的绑定属性,Create和Edit动作方法, 包括Rating属性:

[Bind(Include = "ID,Title,ReleaseDate,Genre,Price,Rating")]

您还需要更新视图模板,以显示浏览器视图中创建和编辑新的评级(Rating)属性。

打开\Views\Movies\Index.cshtml文件,在Price列后面添加Rating的列头。然后添加一个列来显示@item.Rating的值。下面是更新的Index.cshtml视图模板:

@model IEnumerable   
@{    
    ViewBag.Title = "Index";    
}    

Index

@Html.ActionLink("Create New", "Create") @using (Html.BeginForm("Index", "Movies", FormMethod.Get)) { Genre: @Html.DropDownList("movieGenre", "All") Title: @Html.TextBox("SearchString") } @foreach (var item in Model) { }
@Html.DisplayNameFor(model => model.Title) @Html.DisplayNameFor(model => model.ReleaseDate) @Html.DisplayNameFor(model => model.Genre) @Html.DisplayNameFor(model => model.Price) @Html.DisplayNameFor(model => model.Rating)
@Html.DisplayFor(modelItem => item.Title) @Html.DisplayFor(modelItem => item.ReleaseDate) @Html.DisplayFor(modelItem => item.Genre) @Html.DisplayFor(modelItem => item.Price) @Html.DisplayFor(modelItem => item.Rating) @Html.ActionLink("Edit", "Edit", new { id=item.ID }) | @Html.ActionLink("Details", "Details", new { id=item.ID }) | @Html.ActionLink("Delete", "Delete", new { id=item.ID })

下一步,打开\Views\Movies\Create.cshtml文件,并在form标签结束处的附近添加如下代码。您可以在创建新的电影时指定一个电影等级。

@Html.LabelFor(model => model.Price, new { @class = "control-label col-md-2" })
@Html.EditorFor(model => model.Price) @Html.ValidationMessageFor(model => model.Price)
@Html.LabelFor(model => model.Rating, new { @class = "control-label col-md-2" })
@Html.EditorFor(model => model.Rating) @Html.ValidationMessageFor(model => model.Rating)
}
@Html.ActionLink("Back to List", "Index")
@section Scripts { @Scripts.Render("~/bundles/jqueryval") }
@Html.LabelFor(model => model.Price, new { @class = "control-label col-md-2" })
@Html.EditorFor(model => model.Price) @Html.ValidationMessageFor(model => model.Price)
@Html.LabelFor(model => model.Rating, new { @class = "control-label col-md-2" })
@Html.EditorFor(model => model.Rating) @Html.ValidationMessageFor(model => model.Rating)