將新欄位新增至電影模型和資料表
注意
這裡提供本教學課程的更新版本,其中使用 ASP.NET MVC 5 和 Visual Studio 2013。 新的教學指示更安全、更易於遵循且示範更多功能。
在本節,您會使用 Entity Framework Code First Migrations 將部分變更移轉至模型類別,以便讓變更套用至資料庫。
根據預設,使用 Entity Framework Code First 來自動建立資料庫時 (正如稍早在本教學課程操作的動作),Code First 會將表格新增至資料庫,以協助追蹤資料庫的結構描述是否與它產生的來源模型類別同步。 如果未同步,Entity Framework 會擲回錯誤。 這可讓您更輕鬆地在開發階段追蹤您可能只會在執行階段 (透過不明的錯誤) 發現的問題。
為模型變更設定 Code First Migrations
如果您使用 Visual Studio 2012,請按兩下 方案總管 中的Movies.mdf檔案,以開啟資料庫工具。 Visual Studio Express for Web 會顯示 [資料庫總管],Visual Studio 2012 會顯示 [伺服器總管]。 如果您使用 Visual Studio 2010,請使用 SQL Server 物件總管。
在資料庫工具中(資料庫總管、伺服器總管或 SQL Server 物件總管),以滑鼠右鍵單擊MovieDBContext
並選取 [刪除] 以卸除電影資料庫。
流覽回 方案總管。 以滑鼠右鍵按一下 Movies.mdf 檔案,然後選取 [刪除] 移除電影資料庫。
建立應用程式,確認沒有任何錯誤。
在 [工具] 功能表按一下 [NuGet 套件管理員],然後按一下 [套件管理員主控台]。
在提示字元的 [封裝管理員 控制台] 視窗中PM>
,輸入 「Enable-Migrations -ContextTypeName MvcMovie.Models.MovieDBContext」。
Enable-Migrations 命令 (如上所示) 會在新的 Migrations 資料夾中建立 Configuration.cs 檔案。
Visual Studio 會 開啟 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
}
);
}
以滑鼠右鍵按下下方Movie
的紅色波浪線,然後選取 [解析],然後使用MvcMovie.Models;
這樣做會新增下列 using 陳述式:
using MvcMovie.Models;
注意
Code First Migrations 會在每次移轉後 (也就是在套件管理員主控台呼叫 update-database) 呼叫 Seed
方法,且此方法會更新已插入的列,如果列尚不存在則直接插入。
按 CTRL-SHIFT-B 建置專案。(如果您目前未建置,下列步驟將會失敗。
下個步驟是建立初始移轉的 DbMigration
類別。 此移轉會建立新的資料庫,這就是您在 上一個步驟中刪除movie.mdf 檔案的原因。
在 [封裝管理員 控制台] 視窗中,輸入 “add-migration Initial” 命令以建立初始移轉。 「Initial」是用來命名已建立的移轉檔案的任意名稱。
Code First Migrations 會在 Migrations 資料夾中建立另一個類別檔案 (名稱為 {DateStamp}_Initial.cs),且此類別包含的程式碼會建立資料庫結構描述。 移轉檔案名稱的前綴包含時間戳記,有助排序。 檢查 {DateStamp}_Initial.cs檔案,其中包含為Movie DB 建立Movies資料表的指示。 如果您在下方指示更新資料庫,此 {DateStamp}_Initial.cs 檔案就會執行並建立資料庫結構描述。 然後,Seed 方法會執行以便在資料庫填入測試資料。
在 封裝管理員 主控台中,輸入命令 「update-database」 以建立資料庫並執行 Seed 方法。
如果您收到錯誤,指出表格已存在且無法建立,可能是因為您在刪除資料庫之後及執行 update-database
之前執行應用程式。 在此情況下,請再次刪除 Movies.mdf 檔案,然後重試 update-database
命令。 如果仍然收到錯誤,請刪除移轉資料夾和內容,然後開始操作此頁面頂端的指示 (也就是刪除 Movies.mdf 檔案,然後繼續啟用移轉)。
執行應用程式,並前往 /Movies URL。 Seed 資料隨即顯示。
將 Rating 屬性新增至電影模型
首先,新增 Rating
屬性至現有的 Movie
類別。 開啟 Models\Movie.cs 檔案並新增 Rating
屬性,如下所示:
public string Rating { get; set; }
完成的 Movie
類別至此看起來類似下列程式碼:
public class Movie
{
public int ID { get; set; }
public string Title { get; set; }
public DateTime ReleaseDate { get; set; }
public string Genre { get; set; }
public decimal Price { get; set; }
public string Rating { get; set; }
}
使用 [建置電影] 功能表命令或按 CTRL-SHIFT-B 來建>置應用程式。
現在您已更新 類別Model
,您也需要更新 \Views\Movies\Index.cshtml 和 \Views\Movies\Create.cshtml 檢視範本,才能在瀏覽器檢視中顯示新的Rating
屬性。
開啟\Views\Movies\Index.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")
</p>
<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>
接下來,開啟 \Views\Movies\Create.cshtml 檔案,並在表單結尾附近新增下列標記。 這個動作可呈現文字方塊,以便您在建立新電影時指定評分。
<div class="editor-label">
@Html.LabelFor(model => model.Rating)
</div>
<div class="editor-field">
@Html.EditorFor(model => model.Rating)
@Html.ValidationMessageFor(model => model.Rating)
</div>
您現在已更新了應用程式的程式碼,藉此支援新的 Rating
屬性。
現在請執行應用程式,並前往 /Movies URL。 不過執行此操作,您會看到下列其中一個錯誤:
您會看到此錯誤,是因為應用程式中更新的 Movie
模型類別已經與現有資料庫的 Movie
資料表結構描述不同。 (資料庫資料表中沒有任何 Rating
資料行)。
有幾個方法可以解決這個錯誤:
- 讓 Entity Framework 自動卸除資料庫,並重新依據新的模型類別結構描述來建立資料庫。 在測試資料庫上執行主動式開發時,此方法非常方便;它可讓您快速發展模型和資料庫架構。 不過,這麼做的缺點是您會遺失資料庫現有的資料,因此不建議對生產資料庫使用此方法! 使用初始化表達式自動植入具有測試數據的資料庫,通常是開發應用程式的生產力方式。 如需 Entity Framework 資料庫初始化表達式的詳細資訊,請參閱 Tom Dykstra 的 ASP.NET MVC/Entity Framework 教學課程。
- 您可明確修改現有資料庫的結構描述,使其符合模型類別。 這種方法的優點是可以保留您的資料。 您可以手動方式或藉由建立資料庫變更指令碼來進行這項變更。
- 使用 Code First 移轉來更新資料庫結構描述。
在本教學課程中,我們將使用 Code First 移轉。
更新 Seed 方法,讓它為新的欄提供值。 開啟 Migrations\Configuration.cs 檔案,並將 Rating 欄位新增至每個 Movie 物件。
new Movie
{
Title = "When Harry Met Sally",
ReleaseDate = DateTime.Parse("1989-1-11"),
Genre = "Romantic Comedy",
Rating = "G",
Price = 7.99M
},
建立解決方案,然後開啟「套件管理員主控台」視窗,輸入下列命令:
add-migration AddRatingMig
add-migration
命令會告知移轉架構,檢查目前的電影模型與目前的電影資料庫結構描述,並建立必要的程式碼以將資料庫移轉至新的模型。 AddRatingMig 是任意的,用來命名移轉檔案。 在移轉步驟使用有意義的名稱會更加實用。
此命令完成時,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");
}
}
建置方案,然後在 封裝管理員 [控制台] 視窗中輸入 “update-database” 命令。
下圖顯示 [封裝管理員 控制台] 視窗中的輸出(AddRatingMig 前面加上的日期戳記將會不同。
重新執行應用程式,並前往 /Movies URL。 您可以看到新的「Rating」欄位。
按一下 [新建] 連結以新增新電影。 請注意,您已可以新增評分。
按一下 [建立]。 新的電影 (包括評分) 現在會在電影清單中顯示:
您也應該將 Rating
欄位新增至 [編輯]、[詳細數據] 和 [搜尋][索引] 檢視範本。
您可以在 [封裝管理員 控制台] 視窗中再次輸入 “update-database” 命令,而且不會進行任何變更,因為架構符合模型。
在本節中,您已瞭解如何修改模型物件,並讓資料庫與變更維持同步。 您也已藉由範例資料的試用案例,瞭解如何將資料填入新建的資料庫。 接下來,我們會說明如何在模型類別中新增更豐富的驗證邏輯,並啟用可強制執行的商務規則。