ASP.NET MVC 5 - 给电影表和模型添加新字段
在本節(jié)中,您將使用Entity Framework Code First來實(shí)現(xiàn)模型類上的操作。從而使得這些操作和變更,可以應(yīng)用到數(shù)據(jù)庫中。
默認(rèn)情況下,就像您在之前的教程中所作的那樣,使用 Entity Framework Code First自動創(chuàng)建一個(gè)數(shù)據(jù)庫,Code First為數(shù)據(jù)庫所添加的表,將幫助您跟蹤數(shù)據(jù)庫是否和從它生成的模型類是同步的。如果他們不是同步的,Entity Framework將拋出一個(gè)錯(cuò)誤。這非常方便的在開發(fā)時(shí)就可以發(fā)現(xiàn)錯(cuò)誤,否則您可能會在運(yùn)行時(shí)才發(fā)現(xiàn)這個(gè)問題。
為對象模型的變更設(shè)置 Code First Migrations
從解決方案資源管理器中雙擊Movies.mdf,打開數(shù)據(jù)庫工具, 在數(shù)據(jù)庫工具 (數(shù)據(jù)庫資源管理器、 服務(wù)器資源管理器或 SQL Server對象資源管理器),右鍵單擊Movies.mdff,并選擇刪除。
Build應(yīng)用程序,以確保沒有任何編譯錯(cuò)誤。
從工具菜單上,單擊庫包管理器,然后點(diǎn)擊程序包管理器控制臺.
在程序包管理器控制臺窗口,在提示符 PM> 后輸入:
Enable-Migrations -ContextTypeName MvcMovie.Models.MovieDBContext
如上所示的Enable-Migrations 命令,會在Migrations文件夾下創(chuàng)建一個(gè)Configuration.cs 文件。
在Visual Studio 里面打開Configuration.cs 文件. 用下面的代碼替換Seed函數(shù):
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,并選擇“解析(Resolve)”,然后單擊“using MvcMovie.Models;
這樣做會增加下面的語句:
using MvcMovie.Models;
Code First Migrations調(diào)用Seed的方法,每個(gè)遷移(程序包管理器控制臺更新數(shù)據(jù)庫),此方法用于updates數(shù)據(jù)(如果數(shù)據(jù)存在),或inserted數(shù)據(jù)。
在AddOrUpdate方法在下面的代碼執(zhí)行一個(gè)的“upsert”操作:
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 }?
因?yàn)镾eed方法與每個(gè)遷移同時(shí)運(yùn)行時(shí),故,你不能僅僅插入數(shù)據(jù),因?yàn)楫?dāng)你正試圖添加,可能已經(jīng)完成了創(chuàng)建數(shù)據(jù)庫后的第一次遷移。“upsert”操作阻止錯(cuò)誤的發(fā)生,如果你嘗試插入一個(gè)已經(jīng)存在的行,它覆蓋任何數(shù)據(jù)更改,當(dāng)你在測試應(yīng)用程序的同時(shí)。你可能不希望這樣的事情發(fā)生:在某些情況下,當(dāng)您更改數(shù)據(jù)測試時(shí),你希望你的變化后數(shù)據(jù)庫同步更新。在這種情況下,你想要做一個(gè)有條件的插入操作:只有當(dāng)它不存在的時(shí)候,插入一行。
傳遞給AddOrUpdate的方法的第一個(gè)參數(shù), 指定的屬性來使用以檢查是否已存在某行。對于您所提供的測試影片的數(shù)據(jù),Title屬性可以被用于此目的,因?yàn)槊總€(gè)標(biāo)題在列表中是唯一:
context.Movies.AddOrUpdate(i => i.Title,
這個(gè)代碼假設(shè)titiles屬性是唯一的。如果手動添加一個(gè)重復(fù)的標(biāo)題,你會得到下面的異常。
更多關(guān)于 AddOrUpdate 方法的信息,請參見 Take care with EF 4.3 AddOrUpdate Method..
按 CTRL-SHIFT-B 來Build工程。(如果此次Build不成功,以下的步驟將會失敗。)
下一步是創(chuàng)建一個(gè)DbMigration類,用于初始化數(shù)據(jù)庫遷移。此遷移類將創(chuàng)建新的數(shù)據(jù)庫,這也就是為什么在之前的步驟中你要刪除movie.mdf文件。
在軟件包管理器控制臺窗口中,輸入"add-migration Initial"命令來創(chuàng)建初始遷移。" Initial" 的名稱是任意,是用于創(chuàng)建遷移文件的名稱。
Code First Migrations將會在Migrations文件夾中創(chuàng)建另一個(gè)類文件 (文件名為: {DateStamp}_Initial.cs ),此類中包含的代碼將創(chuàng)建數(shù)據(jù)庫的Schema。遷移文件名使用時(shí)間戳作為前綴,以幫助用來排序和查找。查看{DateStamp}_Initial.cs文件,它包含了為電影數(shù)據(jù)庫創(chuàng)建電影表的說明。當(dāng)您更新數(shù)據(jù)庫時(shí), {DateStamp}_Initial.cs文件將會被運(yùn)行并創(chuàng)建 DB 的Schema。然后Seed方法將運(yùn)行,用來填充 DB 的測試數(shù)據(jù)。
在軟件包管理器控制臺中,輸入命令" update-database ",創(chuàng)建數(shù)據(jù)庫并運(yùn)行Seed方法。
如果您收到表已經(jīng)存在并且無法創(chuàng)建的錯(cuò)誤,可能是因?yàn)槟呀?jīng)刪除了數(shù)據(jù)庫,并且在執(zhí)行update-database之前,您運(yùn)行了應(yīng)用程序。在這種情況下,再次刪除Movies.mdf文件,然后重試update-database命令。如果您仍遇到錯(cuò)誤,刪除Migration文件夾及其內(nèi)容,然后從頭開始重做。(即刪除Movies.mdf文件,然后再進(jìn)行Enable-Migrations)
運(yùn)行該應(yīng)用程序,然后瀏覽URL /Movies Seed數(shù)據(jù)顯示如下:
?
為影片模型添加評級(Rating)屬性
給現(xiàn)有的Movie類,添加新的Rating屬性。打開Models\Movie.cs文件并添加如下Rating屬性:
public string Rating { get; set; }
完整的Movie類如下:
public class Movie { public int ID { get; set; } public string Title { get; set; }[Display(Name = "Release Date")] [DataType(DataType.Date)] [DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)] public DateTime ReleaseDate { get; set; } public string Genre { get; set; } public decimal Price { get; set; } public string Rating { get; set; } }Build 應(yīng)用程序 Build>Build Move或CTRL-SHIFT-B.
因?yàn)槟阋呀?jīng)添加了新的字段,電影類的,你還需要Bind,所以這次新的屬性將被包含。更新的綁定屬性,Create和Edit動作方法, 包括Rating屬性:
[Bind(Include = "ID,Title,ReleaseDate,Genre,Price,Rating")]
您還需要更新視圖模板,以顯示瀏覽器視圖中創(chuàng)建和編輯新的評級(Rating)屬性。
打開\Views\Movies\Index.cshtml文件,在Price列后面添加<th>Rating</th>的列頭。然后添加一個(gè)<td>列來顯示@item.Rating的值。下面是更新的Index.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") <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><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文件,并在form標(biāo)簽結(jié)束處的附近添加如下代碼。您可以在創(chuàng)建新的電影時(shí)指定一個(gè)電影等級。
<div class="form-group"> @Html.LabelFor(model => model.Price, new { @class = "control-label col-md-2" }) <div class="col-md-10"> @Html.EditorFor(model => model.Price) @Html.ValidationMessageFor(model => model.Price) </div> </div><div class="form-group"> @Html.LabelFor(model => model.Rating, new { @class = "control-label col-md-2" }) <div class="col-md-10"> @Html.EditorFor(model => model.Rating) @Html.ValidationMessageFor(model => model.Rating) </div> </div><div class="form-group"> <div class="col-md-offset-2 col-md-10"> <input type="submit" value="Create" class="btn btn-default" /> </div> </div> </div> }<div> @Html.ActionLink("Back to List", "Index") </div>@section Scripts { @Scripts.Render("~/bundles/jqueryval") }<div class="form-group">@Html.LabelFor(model => model.Price, new { @class = "control-label col-md-2" })<div class="col-md-10">@Html.EditorFor(model => model.Price)@Html.ValidationMessageFor(model => model.Price)</div></div><div class="form-group">@Html.LabelFor(model => model.Rating, new { @class = "control-label col-md-2" })<div class="col-md-10">@Html.EditorFor(model => model.Rating)@Html.ValidationMessageFor(model => model.Rating)</div></div><div class="form-group"><div class="col-md-offset-2 col-md-10"><input type="submit" value="Create" class="btn btn-default" /></div></div></div>}<div>@Html.ActionLink("Back to List", "Index")</div>@section Scripts {@Scripts.Render("~/bundles/jqueryval")}現(xiàn)在,您已經(jīng)更新應(yīng)用程序代碼以支持了新的Rating屬性。
現(xiàn)在運(yùn)行該應(yīng)用程序,然后瀏覽 /Movies的 URL。然而,當(dāng)您這樣做時(shí),您將看到以下之一的錯(cuò)誤信息:
自從數(shù)據(jù)庫創(chuàng)建后,備份的'MovieDBContext上下文模型已經(jīng)改變。請考慮使用Code First Migrations更新數(shù)據(jù)庫 (http://go.microsoft.com/fwlink/?LinkId=238269).
你看到這個(gè)錯(cuò)誤,因?yàn)楦碌牡腗ovie模型類中比現(xiàn)在Movie現(xiàn)有數(shù)據(jù)庫表的schema不同。 (在數(shù)據(jù)庫表中沒有Rating列。)
有幾個(gè)解決錯(cuò)誤的方法:
1. Entity Framework會自動刪除并重新創(chuàng)建數(shù)據(jù)庫根據(jù)新模型類schema。在開發(fā)周期的早期, 這種方式非常方便,當(dāng)你正在做開發(fā)一個(gè)測試數(shù)據(jù)庫,它可以讓你快速演進(jìn)模型和數(shù)據(jù)庫schema。不足之處,你將失去現(xiàn)有的數(shù)據(jù)庫中的數(shù)據(jù) - 所以對生產(chǎn)數(shù)據(jù)庫你不想使用這種方法! 通常是一個(gè)富有成效的辦法,開發(fā)一個(gè)應(yīng)用程序來初始化數(shù)據(jù)庫的自動測試數(shù)據(jù)。更多關(guān)于Entity Framework database初始化的信息,請參閱Tom Dykstra's fantasticASP.NET MVC/Entity Framework tutorial.
2. 顯式修改現(xiàn)有數(shù)據(jù)庫的架構(gòu),以便它匹配的模型類。這種方法的優(yōu)點(diǎn)是,你保持你的數(shù)據(jù)。可以使手動或通過建立數(shù)據(jù)庫更改腳本實(shí)現(xiàn)它。
3. 使用Code First Migrations來更新數(shù)據(jù)庫schema。
在本教程中,我們將使用Code First Migrations方法。
更新Seed 方法,以使它可以給新列提供一個(gè)值。 打開Migrations\Configuration.cs 文件,在每個(gè)Movie下添加Rating 字段.
new Movie { Title = "When Harry Met Sally", ReleaseDate = DateTime.Parse("1989-1-11"), Genre = "Romantic Comedy", Rating = "PG", Price = 7.99M },編譯解決方案,打開程序包管理器控制臺窗體,輸入如下命令:
add-migration Rating
add-migration命令告訴migration framework,來檢查當(dāng)前電影模型與當(dāng)前的影片 DB Schema并創(chuàng)建必要的代碼以將數(shù)據(jù)庫遷移到新的模型。AddRatingMig 是一個(gè)任意的文件名參數(shù),用于命名migration文件。它將有助于使得遷移步驟成為一個(gè)有意義的名字。
當(dāng)命令完成后,用Visual Studio 打開類文件,新繼承自DbMIgration 類的定義,并在Up 方法中,您可以看到創(chuàng)建新列的代碼:
public partial class AddRatingMig : DbMigration { public override void Up() { AddColumn("dbo.Movies", "Rating", c => c.String()); } public override void Down() { DropColumn("dbo.Movies", "Rating"); } }Build解決方案,然后在 程序包管理器控制臺窗口中輸入"update-database"命令。
下面的圖片顯示了 程序包管理器控制臺窗口的輸出 (日期戳前面添加的評級會有所不同)
重新運(yùn)行應(yīng)用程序,然后瀏覽 /Movies 的 URL。您可以看到新的評級字段。
單擊CreateNew鏈接來添加一部新電影。注意,請您可以為電影添加評級。
單擊Create。新的電影,包括評級,將顯示在電影列表中:
該項(xiàng)目目前正在使用的遷移 (migrations),當(dāng)你添加新的字段或更新數(shù)據(jù)庫Schema, 你不需要刪除數(shù)據(jù)庫。在下一節(jié)中,我們將讓更多的架構(gòu)更改,并使用遷移來更新的數(shù)據(jù)庫。
此外您也應(yīng)該把Rating 字段添加到Edit、Details和Delete的視圖模板中。
您可以再次在 程序包管理器控制臺窗口中輸入"update-database"命令,將不會有任何新的變化,因?yàn)閿?shù)據(jù)庫Schema 和模型類現(xiàn)在是匹配的。然而,運(yùn)行“update-database”將運(yùn)行再次Seed方法,如果你改變?nèi)魏畏N子數(shù)據(jù),更改都將丟失,因?yàn)镾eed的方法upserts數(shù)據(jù)。你可以關(guān)于Seed的方法Tom Dykstra's的流行的ASP.NET MVC/Entity Framework tutorial.。
在本節(jié)中,您看到了如何修改模型對象并始終保持其和數(shù)據(jù)庫Schema的同步。您還學(xué)習(xí)了使用填充示例數(shù)據(jù)來創(chuàng)建新數(shù)據(jù)庫的例子,您可以反復(fù)嘗試。這只是一個(gè)簡單的介紹Code First,更完整的教程的請參閱Creating an Entity Framework Data Model for an ASP.NET MVC Application。接下來,讓我們看看如何將豐富的驗(yàn)證邏輯添加到模型類,并對模型類執(zhí)行一些強(qiáng)制的業(yè)務(wù)規(guī)則驗(yàn)證。后面如果要進(jìn)行ASP.ET MVC的開發(fā),在具備MVC的知識的同時(shí),還可以借助一些開發(fā)工具。使用?ComponentOne Studio ASP.NET MVC?這款輕量級控件,可以助力你的MVC開發(fā)過程。
總結(jié)
以上是生活随笔為你收集整理的ASP.NET MVC 5 - 给电影表和模型添加新字段的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: CCNA培训的第四、第五天
- 下一篇: Android图片的三级缓存