起飛網 ASP.NET MVC 5 學習教程目錄:
- 添加控制器
- 添加視圖
- 修改視圖和布局頁
- 控制器傳遞數據給視圖
- 添加模型
- 創建連接字符串
- 通過控制器訪問模型的數據
- 生成的代碼詳解
- 使用 SQL Server LocalDB
- Edit方法和Edit視圖詳解
- 添加查詢
- Entity Framework 數據遷移之添加字段
- 添加驗證
- Details 和 Delete 方法詳解
在本節中,我們將使用Entity Framework Code First 數據遷移功能將模型類的改變應用到數據庫中。
默認情況下,當我們使用Entity Framework Code First 自動創建一個數據庫,像我們之前教程中講的那樣,Code First 添加一個table幫我們跟蹤數據庫結構是否與模型類同步。如果不同步,Entity Framework 將拋出一個錯誤,這樣更方便我們在開發的時候發現問題,否則只能在運行時通過晦澀的錯誤來查找了。
為模型更改設置 Code First 數據遷移
在解決方案資源管理器中,刪除自動創建的 Movies.mdf 文件。
在工具菜單中,選擇“庫程序包管理器”>“程序包管理器控制台”:
圖1:打開“程序包管理器控制台”菜單項
在“程序包管理器控制台”窗口中輸入:Enable-Migrations -ContextTypeName MvcMovie.Models.MovieDBContext
圖2:運行命令
Enable-Migrations 命令創建了一個Migrations文件夾和Configuration.cs文件。
圖3:新添加的文件
打開 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:創建初始化遷移
Code First Migrations 創建在Migrations文件夾中創建了一個文件(文件名是 {DateStamp}_Initial.cs ),這個類包含了創建數據庫結構的代碼。遷移文件的文件名以DateStamp開頭是為了更好的排序,打開 {DateStamp}_Initial.cs 文件,它包含了為數據庫MovieDB創建Movies表的指令。當你使用下面的命令更新數據庫時,{DateStamp}_Initial.cs 文件將會運行並創建數據庫結構,然后將執行 Seed 方法將測試數據插入數據庫中。
在“程序包管理器控制台”中輸入命令 update-database
:
圖5:執行更新數據庫命令
運行應用程序,瀏覽/Movies 地址,我們在Seed方法中添加的數據如下:
圖6:瀏覽程序
為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:錯誤頁面
出現這個錯誤的原因是Movie模型類發生了變化,而與它對應的數據表 Movie 中並不存在Rating字段。
There are a few approaches to resolving the error:
解決這個問題有以下幾種途徑:
- 讓Entity Framework自動刪除並根據新的模型自動創建數據庫。這種方式在早起開發過程中的測試數據庫中非常方便,它可以快速的修改模型和數據庫結構。另一方面,這樣做將會使你丟失已有的數據,因此這種方式不能用在生產環境的數據庫中。
- 在數據庫中加上Rating字段,使數據庫和Model類的結構相同。這種方式的優點是能夠保留數據,你可以手動修改或使用數據庫腳本修改。
- 使用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:更新數據庫
刷新我們出錯的頁面,你能看到已經加入了Rating字段:
圖9:加入了Rating字段的界面
點擊“Create New”鏈接試着添加一個電影信息,不要忘記為Rating字段賦值。
圖10:新增頁面
輸入完成之后點擊“Create”按鈕,保存電影信息。
圖11:保存后的列表
你還需要在Edit、Details和Delete視圖中添加Rating字段。
如果你再次執行 "update-database" 命令,將不會做出任何修改,因為數據庫結構和模型的結構已經相同了。
現在,通過項目中使用數據遷移,我們在添加字段或更新模型結構的時候不用再刪除數據庫了。在下一節中,我們將對結構做出更多的更改,並使用數據遷移來更新數據庫。
本文同時發布在起飛網,原文地址:http://www.qeefee.com/mvc/mvc-5-adding-a-new-field