给电影表和模型添加新字段

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

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

给现有的Movie类,添加新的Rating属性。打开ModelsMovie.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)属性。

打开ViewsMoviesIndex.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") 
    @using (Html.BeginForm("Index", "Movies", FormMethod.Get)) 
    { 
    <p> 
        Genre: @Html.DropDownList("movieGenre", "All") 
        Title: @Html.TextBox("SearchString") 
        <input type="submit" value="Filter" /> 
    </p> 
    } 
</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>

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

<div class="form-group"> 
            @Html.LabelFor(model => model.Price, new { @class = "control-label col-md-2" }) 
            <div class="col-md-10"> 
                @Html.EditorFor(model => model.Price) 
                @Html.ValidationMessageFor(model => model.Price) 
            </div> 
        </div>

        <div class="form-group"> 
            @Html.LabelFor(model => model.Rating, new { @class = "control-label col-md-2" }) 
            <div class="col-md-10"> 
                @Html.EditorFor(model => model.Rating) 
                @Html.ValidationMessageFor(model => model.Rating) 
            </div> 
        </div>

        <div class="form-group"> 
            <div class="col-md-offset-2 col-md-10"> 
                <input type="submit" value="Create" class="btn btn-default" /> 
            </div> 
        </div> 
    </div> 
}

<div> 
    @Html.ActionLink("Back to List", "Index") 
</div>

@section Scripts { 
    @Scripts.Render("~/bundles/jqueryval") 
}

<div class="form-group">

@Html.LabelFor(model => model.Price, new { @class = "control-label col-md-2" })

<div class="col-md-10">

@Html.EditorFor(model => model.Price)

@Html.ValidationMessageFor(model => model.Price)

</div>

</div>

<div class="form-group">

@Html.LabelFor(model => model.Rating, new { @class = "control-label col-md-2" })

<div class="col-md-10">

@Html.EditorFor(model => model.Rating)

@Html.ValidationMessageFor(model => model.Rating)

</div>

</div>

<div class="form-group">

<div class="col-md-offset-2 col-md-10">

<input type="submit" value="Create" class="btn btn-default" />

</div>

</div>

</div>

}

<div>

@Html.ActionLink("Back to List", "Index")

</div>

@section Scripts {

@Scripts.Render("~/bundles/jqueryval")

}

现在,您已经更新应用程序代码以支持了新的Rating属性。

现在运行该应用程序,然后浏览 /Movies的 URL。然而,当您这样做时,您将看到以下之一的错误信息:

clip_image018
自从数据库创建后,备份的"MovieDBContext上下文模型已经改变。请考虑使用Code First Migrations更新数据库 (http://go.microsoft.com/fwlink/?LinkId=238269).

clip_image020

你看到这个错误,因为更新的的Movie模型类中比现在Movie现有数据库表的schema不同。 (在数据库表中没有Rating列。)

有几个解决错误的方法:

  1. Entity Framework会自动删除并重新创建数据库根据新模型类schema。在开发周期的早期, 这种方式非常方便,当你正在做开发一个测试数据库,它可以让你快速演进模型和数据库schema。不足之处,你将失去现有的数据库中的数据 - 所以对生产数据库你不想使用这种方法! 通常是一个富有成效的办法,开发一个应用程序来初始化数据库的自动测试数据。更多关于Entity Framework database初始化的信息,请参阅Tom Dykstra"s fantasticASP.NET MVC/Entity Framework tutorial.

  2. 显式修改现有数据库的架构,以便它匹配的模型类。这种方法的优点是,你保持你的数据。可以使手动或通过建立数据库更改脚本实现它。

  3. 使用Code First Migrations来更新数据库schema。

在本教程中,我们将使用Code First Migrations方法。

更新Seed 方法,以使它可以给新列提供一个值。 打开MigrationsConfiguration.cs 文件,在每个Movie下添加Rating 字段.

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

编译解决方案,打开程序包管理器控制台窗体,输入如下命令:

add-migration Rating

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"命令。

下面的图片显示了 程序包管理器控制台窗口的输出 (日期戳前面添加的评级会有所不同)

clip_image022

重新运行应用程序,然后浏览 /Movies 的 URL。您可以看到新的评级字段。

clip_image024

单击CreateNew链接来添加一部新电影。注意,请您可以为电影添加评级。

clip_image026

单击Create。新的电影,包括评级,将显示在电影列表中:

clip_image028

该项目目前正在使用的迁移 (migrations),当你添加新的字段或更新数据库Schema, 你不需要删除数据库。在下一节中,我们将让更多的架构更改,并使用迁移来更新的数据库。

此外您也应该把Rating 字段添加到Edit、Details和Delete的视图模板中。

您可以再次在 程序包管理器控制台窗口中输入"update-database"命令,将不会有任何新的变化,因为数据库Schema 和模型类现在是匹配的。然而,运行“update-database”将运行再次Seed方法,如果你改变任何种子数据,更改都将丢失,因为Seed的方法upserts数据。你可以阅读更多关于Seed的方法Tom Dykstra"s的流行的ASP.NET MVC/Entity Framework tutorial.。

在本节中,您看到了如何修改模型对象并始终保持其和数据库Schema的同步。您还学习了使用填充示例数据来创建新数据库的例子,您可以反复尝试。这只是一个简单的介绍Code First,更完整的教程的请参阅Creating an Entity Framework Data Model for an ASP.NET MVC Application。接下来,让我们看看如何将丰富的验证逻辑添加到模型类,并对模型类执行一些强制的业务规则验证。

文章导航