学习ASP .NET MVC5官方教程总结(九)添加新字段

                            学习ASP .NET MVC5官方教程总结(九)添加新字段

       在本章中,我们将使用Entity Framework Code First 数据迁移功能将模型类的改变应用到数据库中。

       默认情况下,当我们使用Entity Framework Code First 自动创建一个数据库,像我们之前教程中讲的那样,Code First 添加一个table帮我们跟踪数据库结构是否与模型类同步。如果不同步,Entity Framework 将抛出一个错误,这样更方便我们在开发的时候发现问题,否则只能在运行时通过晦涩的错误来查找了。

   为模型更改设置 Code First 数据迁移

在解决方案资源管理器中,删除自动创建的 Movies.mdf 文件。

在工具菜单中,选择NuGet程序包管理器>程序包管理器控制台

技术分享

程序包管理器控制台窗口中输入:Enable-Migrations -ContextTypeName MvcMovie.Models.MovieDBContext

Enable-Migrations 命令创建了一个Migrations文件夹和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       }
   );
}

使用这段代码的时候,需要添加 using MvcMovie.Models 的引用。

Code First 数据迁移在每次迁移(在程序包管理器控制台中调用 update-database)的时候都会调用Seed方法。

在进行下一步之前,先编译解决方案,否则下一步会出错误。

下一步,为初始化迁移创建一个 DbMigration 类。这次迁移创建一个新数据库,这也是我们为什么要删除之前的数据库的原因。

程序包管理器控制台窗口,输入命令 add-migration Initial  创建初始化迁移。名称Initial是随意命名的,它用来命名创建好的迁移文件。

技术分享

Code First Migrations 创建在Migrations文件夹中创建了一个文件(文件名是 {DateStamp}_Initial.cs ),这个类包含了创建数据库结构的代码。迁移文件的文件名以DateStamp开头是为了更好的排序,打开 {DateStamp}_Initial.cs  文件,它包含了为数据库MovieDB创建Movies表的指令。当你使用下面的命令更新数据库时,{DateStamp}_Initial.cs  文件将会运行并创建数据库结构,然后将执行 Seed 方法将测试数据插入数据库中。

程序包管理器控制台中输入命令 update-database 

技术分享

运行应用程序,浏览/Movies 地址,我们在Seed方法中添加的数据如下:

技术分享

    为Movie模型添加Rating字段

上面的内容一直在介绍如何进行数据迁移,现在开始为Movie类添加Rating字段,打开Movie.cs 文件,为它添加一个Rating字段,添加后的代码如下

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 视图。修改后的代码如下:

@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") <br />
        <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>
    </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>

修改后的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 地址,这时我们会得到一个错误:

技术分享

出现这个错误的原因是Movie模型类发生了变化,而与它对应的数据表 Movie 中并不存在Rating字段。

解决这个问题有以下几种途径:

l 让Entity Framework自动删除并根据新的模型自动创建数据库。这种方式在早起开发过程中的测试数据库中非常方便,它可以快速的修改模型和数据库结构。另一方面,这样做将会使你丢失已有的数据,因此这种方式不能用在生产环境的数据库中。

2 在数据库中加上Rating字段,使数据库和Model类的结构相同。这种方式的优点是能够保留数据,你可以手动修改或使用数据库脚本修改。

3 使用Code First 迁移来升级数据库结构。

在本章中,我们使用Code First 迁移。

更新Seed 方法,使它为Rating字段提供一个值。

打开 Migrations\Configuration.cs 文件,为每一个Movie对象的Rating字段赋值。

修改后的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",
                    Rating = "PG",
                    Price = 7.99M
                },
                 new Movie
                 {
                     Title = "Ghostbusters ",
                     ReleaseDate = DateTime.Parse("1984-3-13"),
                     Genre = "Comedy",
                     Rating = "PG",
                     Price = 8.99M
                 },
                 new Movie
                 {
                     Title = "Ghostbusters 2",
                     ReleaseDate = DateTime.Parse("1986-2-23"),
                     Genre = "Comedy",
                     Rating = "PG",
                     Price = 9.99M
                 },
               new Movie
               {
                   Title = "Rio Bravo",
                   ReleaseDate = DateTime.Parse("1959-4-15"),
                   Genre = "Western",
                   Rating = "PG",
                   Price = 3.99M
               }
           );
        }

重新编译解决方案,然后打开程序包管理器控制台,执行命令:add-migration Rating

add-migration 命令告诉迁移程序去检查当前的Movie模型与当前数据库之间的差异,创建迁移数据库到最新模型的代码。名称 Rating 是可以随便命名的,此处用来命名迁移文件。

当命令执行完成之后,Visual Studio 会打开刚刚添加的继承自 DbMigration 的类文件,文件中有两个方法 UpDown,分别用来升级和降级数据库。在Up方法中我们可以看到为数据库添加列的代码,而Down方法中的代码则是删除Rating列。

namespace MvcMovie.Migrations
{
    using System;
    using System.Data.Entity.Migrations;
    
    public partial class Rating : DbMigration
    {
        public override void Up()
        {
            AddColumn("dbo.Movies", "Rating", c => c.String());
        }
        
        public override void Down()
        {
            DropColumn("dbo.Movies", "Rating");
        }
    }
}

编译解决方案,然后执行命令 update-database 

运行页面,你能看到已经加入了Rating字段:

技术分享

现在,通过项目中使用数据迁移,我们在添加字段或更新模型结构的时候不用再删除数据库了。在下一章中,我们将对结构做出更多的更改,并使用数据迁移来更新数据库。









郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。