新增欄位

作者: Rick Anderson

注意

本教學課程的更新版本 可在這裡 使用最新版本的 Visual Studio。 新的教學課程會使用ASP.NET Core MVC,這可針對本教學課程提供許多改善。

本教學課程可讓您了解 ASP.NET Core MVC 與控制器和檢視。 Razor Pages 是 ASP.NET Core 的新替代方案,這是頁面型程式設計模型,可讓建置 Web UI 變得更簡單且更具生產力。 建議您在嘗試使用 MVC 版本之前,先試試 Razor 頁面教學課程。 Razor 頁面教學課程:

  • 比較容易學習。
  • 涵蓋更多功能。
  • 這是新應用程式開發的慣用方法。

在本節中,您將使用Entity Framework Code First 移轉將一些變更移轉至模型類別,以便將變更套用至資料庫。

根據預設,當您使用 Entity Framework Code First 自動建立資料庫時,如同您稍早在本教學課程中所做的一樣,Code First 會將資料表新增至資料庫,以協助追蹤資料庫的架構是否與產生的模型類別同步。 如果它們未同步處理,Entity Framework 會擲回錯誤。 這可讓您更輕鬆地追蹤開發階段的問題,否則您只會在執行時間) 隱藏錯誤來尋找 (。

設定模型變更Code First 移轉

流覽至方案總管。 以滑鼠右鍵按一下 Movies.mdf 檔案,然後選取 [刪除 ] 以移除電影資料庫。 如果您沒有看到 Movies.mdf 檔案,請按一下紅色外框下方顯示的 [ 顯示所有檔案 ] 圖示。

顯示 [電影控制器] 點 c 索引標籤並方案總管開啟的螢幕擷取畫面。[顯示所有檔案] 圖示會以紅色圓圈。

建置應用程式,確定沒有任何錯誤。

從 [ 工具] 功能表中,按一下 [NuGet 套件管理員 ],然後按一下 [ 套件管理員主控台]。

新增套件管理員

在 [ 套件管理員主控台] 視窗中, PM> 于提示中輸入

Enable-Migrations -CoNtextTypeName MvcMovie.Models.MovieDBCoNtext

顯示 [套件管理員主控台] 視窗的螢幕擷取畫面。[啟用移轉] 命令中的文字會反白顯示。

[啟用移轉] 命令 (如上所示,) 會在新的Migrations資料夾中建立Configuration.cs檔案。

顯示方案總管的螢幕擷取畫面。已選取 [移轉] 資料夾的 [組態點 c s] 子資料夾。

Visual Studio 會開啟 Configuration.cs 檔案。 Seed以下列程式碼取代Configuration.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
       }
   );
   
}

將滑鼠停留在下方紅色波浪線上方 Movie ,然後按一下 ,然後按一下 Show Potential Fixes[使用MvcMovie.Models] ;

顯示 [顯示潛在修正] 功能表的螢幕擷取畫面。已選取 [使用 M V C 電影點模型],並顯示找不到警示。

這麼做會新增下列 using 語句:

using MvcMovie.Models;

注意

Code First 移轉 Seed 在每次移轉 (之後呼叫 方法,也就是呼叫 Package Manager 主控台中的update-database) ,而且此方法會更新已插入的資料列,或如果它們還不存在,則會插入它們。

下列程式碼中的 AddOrUpdate 方法會執行 「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
    }

由於 Seed 方法會隨每個移轉一起執行,因此您無法只插入資料,因為您嘗試新增的資料列在建立資料庫的第一次移轉之後就已經存在。 「upsert」作業可防止當您嘗試插入已經存在的資料列時所發生的錯誤,但是它會覆寫您在測試應用程式時可能所做的任何資料變更。 在某些資料表中使用測試資料,您可能不想發生這種情況:在某些情況下,當您在測試時變更資料時,您希望在資料庫更新之後保留變更。 在此情況下,您想要執行條件式插入作業:只有在資料列不存在時才插入資料列。

傳遞至 AddOrUpdate 方法的第一個參數會指定要用來檢查資料列是否存在的屬性。 針對您提供的測試電影資料,屬性可用於此用途, Title 因為清單中的每個標題都是唯一的:

context.Movies.AddOrUpdate(i => i.Title,

此程式碼假設標題是唯一的。 如果您手動新增重複的標題,下次執行移轉時,將會收到下列例外狀況。

序列包含一個以上的元素

如需 AddOrUpdate 方法的詳細資訊,請參閱 使用 EF 4.3 AddOrUpdate 方法處理

按 CTRL-SHIFT-B 來建置專案。 (如果您目前未建置,下列步驟將會失敗。)

下一個步驟是建立 DbMigration 初始移轉的類別。 此移轉會建立新的資料庫,這就是您在上一個步驟中刪除 movie.mdf 檔案的原因。

在 [ 套件管理員主控台] 視窗中,輸入命令 add-migration Initial 以建立初始移轉。 名稱 「Initial」 是任意的,用來命名所建立的移轉檔案。

顯示套件管理員主控台的螢幕擷取畫面。新增移轉命令中的文字會反白顯示。

Code First 移轉在Migrations資料夾中建立另一個類別檔案, (名稱為 {DateStamp}_Initial.cs ) ,而且此類別包含建立資料庫架構的程式碼。 移轉檔案名是使用時間戳預先修正,以協助排序。 檢查 {DateStamp}_Initial.cs 檔案,其中包含建立 Movies 電影 DB 資料表的指示。 當您在下列指示中更新資料庫時,此 {DateStamp}_Initial.cs 檔案將會執行並建立 DB 架構。 然後 ,Seed 方法會執行 以填入資料庫測試資料。

[套件管理員主控台]中,輸入 命令 update-database 以建立資料庫並執行 Seed 方法。

顯示套件管理員主控台的螢幕擷取畫面。更新資料庫命令位於視窗中。

如果您收到錯誤,指出資料表已存在且無法建立,可能是因為您在刪除資料庫之後執行應用程式,並在執行 之前執行 update-database 。 在此情況下,請再次刪除 Movies.mdf 檔案,然後重試 update-database 命令。 如果您仍然收到錯誤,請刪除移轉資料夾和內容,然後從此頁面頂端的指示開始, (刪除 Movies.mdf 檔案,然後繼續進行 Enable-Migrations) 。 如果您仍然收到錯誤,請開啟SQL Server 物件總管並從清單中移除資料庫。 如果您收到錯誤,指出「無法附加 .mdf 做為資料庫」檔案,請將 Initial Catalog 屬性移除為 web.config 檔案中連接字串的一部分。

執行應用程式並流覽至 /Movies URL。 會顯示種子資料。

顯示 M V C 電影索引的螢幕擷取畫面,其中列出四部電影。

將 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; }

    [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; }
}

建置應用程式 (Ctrl+Shift+B) 。

因為您已將新的欄位新增至 Movie 類別,所以也需要更新系結 允許清單 ,以便包含這個新的屬性。 bind更新 和 Edit 動作方法的屬性 Create ,以包含 Rating 屬性:

[Bind(Include = "ID,Title,ReleaseDate,Genre,Price,Rating")]

您也需要更新檢視範本,以便在瀏覽器檢視中顯示、建立和編輯新的 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")
    @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 檔案,並新增 Rating 具有下列醒目提示標記的欄位。 這會轉譯文字方塊,讓您可以在建立新電影時指定評等。

<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, new { htmlAttributes = new { @class = "form-control" } })
                @Html.ValidationMessageFor(model => model.Price, "", new { @class = "text-danger" })
            </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, new { htmlAttributes = new { @class = "form-control" } })
                @Html.ValidationMessageFor(model => model.Rating, "", new { @class = "text-danger" })
            </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")
}

您現在已更新應用程式程式碼以支援新的 Rating 屬性。

執行應用程式並流覽至 /Movies URL。 不過,當您這樣做時,您會看到下列其中一個錯誤:

顯示例外狀況使用者未處理錯誤的螢幕擷取畫面。

建立資料庫之後,支援 'MovieDBCoNtext' 內容的模型已變更。 請考慮使用 Code First 移轉來更新資料庫」(https://go.microsoft.com/fwlink/?LinkId=238269)。

顯示具有代理程式更新伺服器錯誤之瀏覽器的螢幕擷取畫面。

您會看到此錯誤,因為應用程式中更新 Movie 的模型類別現在與現有資料庫的資料表架構 Movie 不同。 (資料庫資料表中沒有任何 Rating 資料行)。

有幾個方法可以解決這個錯誤:

  1. 讓 Entity Framework 自動卸除資料庫,並重新依據新的模型類別結構描述來建立資料庫。 在開發週期早期,當您在測試資料庫上進行開發時,這個方法會很方便;其可讓您一併調整模型和資料庫結構描述,更加快速。 不過,缺點是您會遺失資料庫中的現有資料,因此您 不想 在生產資料庫上使用此方法! 使用初始設定式將測試資料自動植入資料庫,通常是開發應用程式的有效方式。 如需 Entity Framework 資料庫初始化運算式的詳細資訊,請參閱 ASP.NET MVC/Entity Framework 教學課程
  2. 您可明確修改現有資料庫的結構描述,使其符合模型類別。 這種方法的優點是可以保留您的資料。 您可以手動方式或藉由建立資料庫變更指令碼來進行這項變更。
  3. 使用 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 = "PG",
    Price = 7.99M
},

建置方案,然後開啟 [ 套件管理員主控台] 視窗,然後輸入下列命令:

add-migration Rating

命令 add-migration 會告訴移轉架構使用目前的電影 DB 架構檢查目前的電影模型,並建立必要的程式碼,以將資料庫移轉至新的模型。 評等名稱是任意的,用來命名移轉檔案。 使用有意義的移轉步驟名稱會很有説明。

當此命令完成時,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 命令。

下圖顯示 [ 套件管理員主控台 ] 視窗中的輸出, ([日期戳記] 前的 評分 將會不同。)

顯示 [套件管理員主控台] 視窗的螢幕擷取畫面,其中已輸入更新資料庫命令。

重新執行應用程式並流覽至 /Movies URL。 您可以看到新的 [評等] 欄位。

顯示 [M V C 影片索引] 清單的螢幕擷取畫面,其中已新增 [評分] 欄位。

按一下 [ 新建] 連結以新增電影。 請注意,您可以新增評等。

7_CreateRioII

按一下 [建立]。 新的電影,包括評等,現在會顯示在電影清單中:

7_ourNewMovie_SM

現在專案正在使用移轉,您不需要在新增欄位或更新架構時卸載資料庫。 在下一節中,我們將進行更多架構變更,並使用移轉來更新資料庫。

您也應該將 Rating 欄位新增至 [編輯]、[詳細資料] 和 [刪除] 檢視範本。

您可以在 [套件管理員主控台 ] 視窗中再次輸入 「update-database」 命令,而且不會執行任何移轉程式碼,因為架構符合模型。 不過,執行 「update-database」 會再次執行 Seed 方法,而且如果您變更任何種子資料,則變更將會遺失,因為 Seed 方法會更新插入資料。 您可以在 Tom Dykstra 的熱門ASP.NET MVC/Entity Framework 教學課程中深入瞭解 Seed 方法。

在本節中,您已瞭解如何修改模型物件,並讓資料庫與變更保持同步。 您也已瞭解如何使用範例資料填入新建立的資料庫,以便試用案例。 這只是程式碼優先的快速簡介,請參閱建立 適用于 ASP.NET MVC 應用程式的 Entity Framework 資料模型 ,以取得主題的更完整教學課程。 接下來,讓我們看看如何將更豐富的驗證邏輯新增至模型類別,並強制執行一些商務規則。