[.NET MVC4 入門系列06] 在Movie Model和表中添加新字段(Code First Migrations)


一、Entity Framework Code First 簡析:

Entity Framework Code First是指,先使用Entity Framework來建立要使用Model類代碼,然后由Entity Framework來為我們自動創建數據庫和表。

創建過程中,Code First模式會檢查數據庫結構是否和Model類同步。如果不同步,Entity Framework會拋出錯誤。

【白話總結】

  Code First模式指的就是——現有Model類代碼,然后Entity Framework自動生成對應的數據庫和表。

 

二、為Model的更改設置Code First 遷移(Setting up Code First Migrations for Model Changes)

Code First 遷移(Code First Migrations):

目的、功能: 使Model類和自動生成的數據庫、表同步。當Model代碼更改時,通過更新數據庫命令,可以生成新的和Model新類結構相一致的數據庫、表。

操作步驟:

步驟1:刪除原有數據庫連接和數據庫

        從服務器資源管理器中,找到MovieDBContext,將其刪除;

        在解決方案資源管理器中,找到Movies.mdf,將其刪除;

   重新生成項目

步驟2: 使用程序包管理器控制台輸入命令,建立Code First Migrations

       工具——庫程序包管理器——程序包管理器控制台,輸入命令:

       Enable-Migrations -ContextTypeName MvcApplication1.Models.MovieDBContext

       

 

  為我們的項目開啟Code First 遷移。這回同時生成一個Configuration.cs在項目的/Migrations/目錄下。

步驟3:更改Configuration.cs中Seed()方法代碼:

 

 1         protected override void Seed(MvcApplication1.Models.MovieDBContext context)
 2         {
 3             //  This method will be called after migrating to the latest version.
 4 
 5             //  You can use the DbSet<T>.AddOrUpdate() helper extension method 
 6             //  to avoid creating duplicate seed data. E.g.
 7             //
 8             //    context.People.AddOrUpdate(
 9             //      p => p.FullName,
10             //      new Person { FullName = "Andrew Peters" },
11             //      new Person { FullName = "Brice Lambson" },
12             //      new Person { FullName = "Rowan Miller" }
13             //    );
14             //
15             context.Movies.AddOrUpdate(i => i.Title,
16                 new Movie
17             {
18                 Title = "When Harry Met Sally",
19                 ReleaseDate = DateTime.Parse("1989-1-11"),
20                 Genre = "Romantic Comedy",
21                 Price = 7.99M
22             },
23 
24              new Movie
25              {
26                  Title = "Ghostbusters ",
27                  ReleaseDate = DateTime.Parse("1984-3-13"),
28                  Genre = "Comedy",
29                  Price = 8.99M
30              },
31 
32              new Movie
33              {
34                  Title = "Ghostbusters 2",
35                  ReleaseDate = DateTime.Parse("1986-2-23"),
36                  Genre = "Comedy",
37                  Price = 9.99M
38              },
39 
40             new Movie
41             {
42                 Title = "Rio Bravo",
43                 ReleaseDate = DateTime.Parse("1959-4-15"),
44                 Genre = "Western",
45                 Price = 3.99M
46             });
47         }

 

這個代碼在數據庫被更新或新建后,被系統自動調用,用來初始化數據,提供測試用數據。注意導入命名空間:

usingMvcMovie.Models;

 重新生成項目

步驟4:生成遷移類Initial:DbMigration

  遷移類用來創建新數據庫

  程序包管理器控制台中輸入命令add-migration Initial

這會在/Migrations/目錄下生成一個帶有時間戳的Initial.cs代碼,其中包含Initinal類派生自DbMigration

 

 1 namespace MvcApplication1.Migrations
 2 {
 3     using System;
 4     using System.Data.Entity.Migrations;
 5     
 6     public partial class Initial : DbMigration
 7     {
 8         public override void Up()
 9         {
10             CreateTable(
11                 "dbo.Movies",
12                 c => new
13                     {
14                         ID = c.Int(nullable: false, identity: true),
15                         Title = c.String(),
16                         ReleaseDate = c.DateTime(nullable: false),
17                         Genre = c.String(),
18                         Price = c.Decimal(nullable: false, precision: 18, scale: 2),
19                     })
20                 .PrimaryKey(t => t.ID);
21             
22         }
23         
24         public override void Down()
25         {
26             DropTable("dbo.Movies");
27         }
28     }
29 }

 

步驟5:更新數據庫

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

  這個命令會先運行步驟4中的Initial的Down和Up方法,創建新數據庫;

  然后運行Seed方法添加測試數據,從而同步Model類。

 

三、為Movie類Model 添加一個Rating屬性

  步驟1:更改/Model/Movie.cs ,添加Rating屬性:

1   public class Movie
2     {
3         public int ID { get; set; }
4         public string Title { get; set; }
5         public DateTime ReleaseDate { get; set; }
6         public string Genre { get; set; }
7         public decimal Price { get; set; }
8         public string Rating { get; set; } 9     }

  步驟2:重新生成項目,更改View

      1)改 \Views\Movies\index.html

     

 1 @model IEnumerable<MvcMovie.Models.Movie>
 2 
 3 @{
 4     ViewBag.Title = "Index";
 5 }
 6 
 7 <h2>Index</h2>
 8 
 9 <p>
10     @Html.ActionLink("Create New", "Create")
11 </p>
12 <table>
13     <tr>
14         <th>
15             @Html.DisplayNameFor(model => model.Title)
16         </th>
17         <th>
18             @Html.DisplayNameFor(model => model.ReleaseDate)
19         </th>
20         <th>
21             @Html.DisplayNameFor(model => model.Genre)
22         </th>
23         <th>
24             @Html.DisplayNameFor(model => model.Price)
25         </th>
26          <th>
27  @Html.DisplayNameFor(model => model.Rating) 28         </th>
29         <th></th>
30     </tr>
31 
32 @foreach (var item in Model) {
33     <tr>
34         <td>
35             @Html.DisplayFor(modelItem => item.Title)
36         </td>
37         <td>
38             @Html.DisplayFor(modelItem => item.ReleaseDate)
39         </td>
40         <td>
41  @Html.DisplayFor(modelItem => item.Genre) 42         </td>
43         <td>
44             @Html.DisplayFor(modelItem => item.Price)
45         </td>
46         <td>
47             @Html.DisplayFor(modelItem => item.Rating)
48         </td>
49         <td>
50             @Html.ActionLink("Edit", "Edit", new { id=item.ID }) |
51             @Html.ActionLink("Details", "Details", new { id=item.ID }) |
52             @Html.ActionLink("Delete", "Delete", new { id=item.ID })
53         </td>
54     </tr>
55 }
56 
57 </table>

  2)改 \Views\Movies\Create.html 

 1 @model MvcApplication1.Models.Movie
 2 
 3 @{
 4     ViewBag.Title = "Create";
 5 }
 6 
 7 <h2>Create</h2>
 8 
 9 @using (Html.BeginForm()) {
10     @Html.AntiForgeryToken()
11     @Html.ValidationSummary(true)
12 
13     <fieldset>
14         <legend>Movie</legend>
15 
16         <div class="editor-label">
17             @Html.LabelFor(model => model.Title)
18         </div>
19         <div class="editor-field">
20             @Html.EditorFor(model => model.Title)
21             @Html.ValidationMessageFor(model => model.Title)
22         </div>
23 
24         <div class="editor-label">
25             @Html.LabelFor(model => model.ReleaseDate)
26         </div>
27         <div class="editor-field">
28             @Html.EditorFor(model => model.ReleaseDate)
29             @Html.ValidationMessageFor(model => model.ReleaseDate)
30         </div>
31 
32         <div class="editor-label">
33             @Html.LabelFor(model => model.Genre)
34         </div>
35         <div class="editor-field">
36             @Html.EditorFor(model => model.Genre)
37             @Html.ValidationMessageFor(model => model.Genre)
38         </div>
39 
40         <div class="editor-label">
41             @Html.LabelFor(model => model.Price)
42         </div>
43         <div class="editor-field">
44             @Html.EditorFor(model => model.Price)
45             @Html.ValidationMessageFor(model => model.Price)
46         </div>
47 
48         <div class="editor-label">
49  @Html.LabelFor(model=>model.Rating) 50         </div>
51 
52         <div class="editor-field">
53  @Html.EditorFor(model=>model.Rating) 54  @Html.ValidationMessageFor(model=>model.Rating) 55         </div>
56         <p>
57             <input type="submit" value="Create" />
58         </p>
59     </fieldset>
60 }
61 
62 <div>
63     @Html.ActionLink("Back to List", "Index")
64 </div>
65 
66 @section Scripts {
67     @Scripts.Render("~/bundles/jqueryval")
68 }

  這時,編譯並運行網站,會出現一個錯誤:

提示MovieDBContext更改,和數據庫不匹配。

可以有下面多種途徑解決這個錯誤:

  1)使用Entity Framework 自動刪除、並基於新的model class 架構 重建數據庫。如果在測試數據庫上使用這種方式非常方便。然而,不適合應用到已經有大量數據的數據庫上,因為重建會丟失所有原有數據。

Using an initializer to automatically seed a database with test data is often a productive way to develope an application. For more information on Entity Framework database initializers, see Tom Dykstra's ASP.NET MVC/Entity Framework tutorial.

  2)更改數據庫結構,以匹配model類架構。

    這種方式的優勢是可以保留數據庫原有記錄。可以手動更改,也可以編寫數據庫更新腳本代碼

  3)使用 Code First 遷移(Code First Migrations)來更新數據庫架構。

    這時我們當前這篇博文使用的方式。

  步驟3:使用Code First Migrations 來更新數據庫架構:

  1)首先打開 \Migrations\Configuration.cs 文件,為每個Movie臨時對象添加Rating字段:

 1  protected override void Seed(MvcApplication1.Models.MovieDBContext context)
 2         {
 3             //  This method will be called after migrating to the latest version.
 4 
 5             //  You can use the DbSet<T>.AddOrUpdate() helper extension method 
 6             //  to avoid creating duplicate seed data. E.g.
 7             //
 8             //    context.People.AddOrUpdate(
 9             //      p => p.FullName,
10             //      new Person { FullName = "Andrew Peters" },
11             //      new Person { FullName = "Brice Lambson" },
12             //      new Person { FullName = "Rowan Miller" }
13             //    );
14             //
15             context.Movies.AddOrUpdate(i => i.Title,
16                 new Movie
17             {
18                 Title = "When Harry Met Sally",
19                 ReleaseDate = DateTime.Parse("1989-1-11"),
20                 Genre = "Romantic Comedy",
21                 Rating = "G", 22                 Price = 7.99M
23             },
24 
25              new Movie
26              {
27                  Title = "Ghostbusters ",
28                  ReleaseDate = DateTime.Parse("1984-3-13"),
29                  Genre = "Comedy",
30                  Rating = "G", 31                  Price = 8.99M
32              },
33 
34              new Movie
35              {
36                  Title = "Ghostbusters 2",
37                  ReleaseDate = DateTime.Parse("1986-2-23"),
38                  Genre = "Comedy",
39                  Rating = "G", 40                  Price = 9.99M
41              },
42 
43             new Movie
44             {
45                 Title = "Rio Bravo",
46                 ReleaseDate = DateTime.Parse("1959-4-15"),
47                 Genre = "Western",
48                 Rating = "G", 49                 Price = 3.99M
50             });
51         }

  2)打開程序包管理器控制台中輸入命令

     add-migration AddRatingMig

      如圖:

   這句命令是添加一個遷移更改,並將其命名為"AddRatingMig".

  會自動檢查當前的Model框架,比對數據庫,生成一個加有時間戳命名的遷移代碼:

   如上圖,代碼中包含一個Up()和Down()方法

   3)重新生成項目,並打開程序包管理器控制台中輸入命令

     update-database

  更新數據庫架構,如圖:

  4)運行

  可以在首頁(index)和create中發現新加入的Rating列

  但是Edit和Detail中還沒有,那是因為我們只處理了index.cshtml和create.cshtml,讀者可以自行試着模仿前面的操作改動Edit.cshtml和Detail.cshtml、SearchIndex


 

初學MS 的MVC 4,參照微軟www.asp.net/mvc 中的入門項目,寫個MVC 4的入門系列,以供復習和分享。

微軟入門項目:http://www.asp.net/mvc/tutorials/mvc-4/getting-started-with-aspnet-mvc4/intro-to-aspnet-mvc-4

【目錄】

1.[.NET MVC4 入門系列01]Helloworld MVC 4 第一個MVC4程序

2.  [.NET MVC4 入門系列02]MVC Movie 為項目添加Model

3.  [.NET MVC4 入門系列03]使用Controller訪問Model中數據

4.  [.NET MVC4 入門系列04]Controller和View間交互原理

5. .NET MVC4 入門系列05]添加自定義查詢頁Search

6. [.NET MVC4 入門系列06] 在Movie Model和表中添加新字段(Code First Migrations)

7. [.NET MVC4 入門系列07] 在Model模型模塊中添加驗證

 


免責聲明!

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



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