ASP.NET MVC 5 學習教程:數據遷移之添加字段


起飛網 ASP.NET MVC 5 學習教程目錄:

在本節中,我們將使用Entity Framework Code First 數據遷移功能將模型類的改變應用到數據庫中。

默認情況下,當我們使用Entity Framework Code First 自動創建一個數據庫,像我們之前教程中講的那樣,Code First 添加一個table幫我們跟蹤數據庫結構是否與模型類同步。如果不同步,Entity Framework 將拋出一個錯誤,這樣更方便我們在開發的時候發現問題,否則只能在運行時通過晦澀的錯誤來查找了。

為模型更改設置 Code First 數據遷移

在解決方案資源管理器中,刪除自動創建的 Movies.mdf 文件。

在工具菜單中,選擇“庫程序包管理器”>“程序包管理器控制台”:

圖1:打開“程序包管理器控制台”菜單項

image

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

圖2:運行命令

image

Enable-Migrations 命令創建了一個Migrations文件夾和Configuration.cs文件。

圖3:新添加的文件

image

打開 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 類。這次遷移創建一個新數據庫,這也是我們為什么要刪除之前的數據庫的原因。

在“程序包管理器控制台”窗口,輸入命令 add-migration Initial  創建初始化遷移。名稱“Initial”是隨意命名的,它用來命名創建好的遷移文件。

圖4:創建初始化遷移

image

Code First Migrations 創建在Migrations文件夾中創建了一個文件(文件名是 {DateStamp}_Initial.cs ),這個類包含了創建數據庫結構的代碼。遷移文件的文件名以DateStamp開頭是為了更好的排序,打開 {DateStamp}_Initial.cs  文件,它包含了為數據庫MovieDB創建Movies表的指令。當你使用下面的命令更新數據庫時,{DateStamp}_Initial.cs  文件將會運行並創建數據庫結構,然后將執行 Seed 方法將測試數據插入數據庫中。

在“程序包管理器控制台”中輸入命令 update-database

圖5:執行更新數據庫命令

image

運行應用程序,瀏覽/Movies 地址,我們在Seed方法中添加的數據如下:

圖6:瀏覽程序

image

為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:錯誤頁面

image

出現這個錯誤的原因是Movie模型類發生了變化,而與它對應的數據表 Movie 中並不存在Rating字段。

There are a few approaches to resolving the error:

解決這個問題有以下幾種途徑:

  1. 讓Entity Framework自動刪除並根據新的模型自動創建數據庫。這種方式在早起開發過程中的測試數據庫中非常方便,它可以快速的修改模型和數據庫結構。另一方面,這樣做將會使你丟失已有的數據,因此這種方式不能用在生產環境的數據庫中。
  2. 在數據庫中加上Rating字段,使數據庫和Model類的結構相同。這種方式的優點是能夠保留數據,你可以手動修改或使用數據庫腳本修改。
  3. 使用Code First 遷移來升級數據庫結構。

在本教程中,我們使用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");
    }
}

編譯解決方案,然后執行命令 update-database 。“程序包管理器控制台”窗口的輸出如下圖(Rating前的時間戳可能不盡相同):

圖8:更新數據庫

image

刷新我們出錯的頁面,你能看到已經加入了Rating字段:

圖9:加入了Rating字段的界面

image

點擊“Create New”鏈接試着添加一個電影信息,不要忘記為Rating字段賦值。

圖10:新增頁面

image

輸入完成之后點擊“Create”按鈕,保存電影信息。

圖11:保存后的列表

image

 

你還需要在Edit、Details和Delete視圖中添加Rating字段。

如果你再次執行 "update-database" 命令,將不會做出任何修改,因為數據庫結構和模型的結構已經相同了。

現在,通過項目中使用數據遷移,我們在添加字段或更新模型結構的時候不用再刪除數據庫了。在下一節中,我們將對結構做出更多的更改,並使用數據遷移來更新數據庫。

本文同時發布在起飛網,原文地址:http://www.qeefee.com/mvc/mvc-5-adding-a-new-field


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM