Movie モデルとテーブルに新しいフィールドを追加する

作成者 : Rick Anderson

Note

このチュートリアルの更新版は、MVC 5 とVisual Studio 2013 ASP.NET 使用するこちらにあります。 より安全で、従う方がはるかに簡単で、より多くの機能を示します。

このセクションでは、Entity Framework Code First Migrationsを使用してモデル クラスにいくつかの変更を移行し、変更がデータベースに適用されるようにします。

既定では、このチュートリアルで前に行ったように Entity Framework Code First を使用してデータベースを自動的に作成すると、Code First によってデータベースにテーブルが追加され、データベースのスキーマが生成元のモデル クラスと同期しているかどうかを追跡できます。 同期されていない場合、Entity Framework はエラーをスローします。 これにより、実行時に (あいまいなエラーによって) 見つからない可能性がある開発時の問題を簡単に追跡できます。

モデル変更のCode First Migrationsの設定

Visual Studio 2012 を使用している場合は、ソリューション エクスプローラーから Movies.mdf ファイルをダブルクリックしてデータベース ツールを開きます。 Web 用Visual Studio Expressデータベース エクスプローラーが表示され、Visual Studio 2012 にはサーバー エクスプローラーが表示されます。 Visual Studio 2010 を使用している場合は、SQL Server オブジェクト エクスプローラーを使用します。

データベース ツール (データベース エクスプローラー、サーバー エクスプローラー、またはSQL Server オブジェクト エクスプローラー) で MovieDBContext を右クリックし、 [削除] を選択してムービー データベースを削除します

[サーバー エクスプローラー] ウィンドウを示すスクリーンショット。[Movie D B Context]\(ムービー D B コンテキスト\) 右クリック メニューで [削除] が選択されています。

ソリューション エクスプローラーに戻ります。 Movies.mdf ファイルを右クリックし、[削除] を選択して movies データベースを削除します

ソリューション エクスプローラー ウィンドウを示すスクリーンショット。[ムービー] ドット m d f 右クリック メニューで [削除] が選択されています。

アプリケーションをビルドしてエラーがないことを確認します。

[ツール] メニューの [NuGet パッケージ マネージャー] をクリックし、[パッケージ マネージャー コンソール] をクリックします。

パックマンの追加

プロンプトの [パッケージ マネージャー コンソール ] ウィンドウで PM> 、「Enable-Migrations -ContextTypeName MvcMovie.Models.MovieDBContext」と入力します。

[パッケージ マネージャー コンソール] ウィンドウを示すスクリーンショット。[移行の有効化] コマンドが入力されます。

Enable-Migrations コマンド (上記) は、新しい Migrations フォルダーに Configuration.cs ファイルを作成します。

ソリューション エクスプローラー ウィンドウを示すスクリーンショット。Migrations フォルダーと Configuration dot cs ファイルは赤で囲まれています。

Visual Studio によって Configuration.cs ファイルが 開きます。 SeedConfiguration.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の赤い波線を右クリックし、[解決] を選択し、MvcMovie.Models を使用します。

[ムービー] 右クリック メニューで [解決] が選択されていることを示すスクリーンショット。

これにより、次の using ステートメントが追加されます。

using MvcMovie.Models;

Note

Code First Migrationsは、移行のたびに メソッドをSeed呼び出します (つまり、パッケージ マネージャー コンソールで update-database を呼び出す)、このメソッドは既に挿入されている行を更新するか、まだ存在しない場合は挿入します。

Ctrl キーを押しながら Shift キーを押しながら B キーを押して、プロジェクトをビルドします。(この時点でビルドしないと、次の手順は失敗します)。

次の手順では、最初の移行用の DbMigration クラスを作成します。 へのこの移行によって新しいデータベースが作成されます。そのため、前の手順で movie.mdf ファイルを削除しました。

[パッケージ マネージャー コンソール] ウィンドウで、"add-migration Initial" コマンドを入力して初期移行を作成します。 "Initial" という名前は任意であり、作成された移行ファイルに名前を付けるために使用されます。

[パッケージ マネージャー コンソール] ウィンドウを示すスクリーンショット。[この移行ファイルのDesigner コード] で始まる段落が強調表示されています。

Code First Migrationsは、({DateStamp}_Initial.cs という名前の) Migrations フォルダーに別のクラス ファイルを作成します。このクラスには、データベース スキーマを作成するコードが含まれています。 移行のファイル名の先頭には、並べ替えに役立つタイムスタンプが付きます。 {DateStamp}_Initial.cs ファイルを調べます。これには、Movie DB の Movies テーブルを作成する手順が含まれています。 次の手順でデータベースを更新すると、この {DateStamp}_Initial.cs ファイルが実行され、DB スキーマが作成されます。 次に、 Seed メソッドが実行され、DB にテスト データが設定されます。

パッケージ マネージャー コンソールで、"update-database" コマンドを入力してデータベースを作成し、Seed メソッドを実行します。

[パッケージ マネージャー コンソール] ウィンドウを示すスクリーンショット。データベース更新コマンドが入力されます。

テーブルが既に存在し、作成できないことを示すエラーが発生した場合は、データベースを削除した後、および を実行する前にアプリケーションを実行した update-database可能性があります。 その場合は、 Movies.mdf ファイルをもう一度削除し、コマンドを update-database 再試行します。 それでもエラーが発生する場合は、移行フォルダーとコンテンツを削除し、このページの上部にある指示から始めます (つまり 、Movies.mdf ファイルを削除してから Enable-Migrations に進みます)。

アプリケーションを実行し、 /Movies URL に移動します。 シード データが表示されます。

4 つのムービーの一覧が表示された [M V C Movie Index] ページを示すスクリーンショット。

ムービー モデルへの評価プロパティの追加

まず、既存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; }
    public DateTime ReleaseDate { get; set; }
    public string Genre { get; set; }
    public decimal Price { get; set; }
    public string Rating { get; set; }
}

[Build Movie]\(ムービーのビルド\) メニュー コマンドを使用するか、Ctrl + Shift + B キーを押して、アプリケーションをビルド>します。

クラスを更新Modelしたので、ブラウザー ビューに新しいRatingプロパティを表示するために、\Views\Movies\Index.cshtml および \Views\Movies\Create.cshtml ビュー テンプレートも更新する必要があります。

\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 列はありません)。

このエラーを解決するための手法がいくつかあります。

  1. Entity Framework に、新しいモデル クラス スキーマに基づいてデータベースを自動的にドロップさせ、再作成させます。 この方法は、テスト データベースでアクティブな開発を行う場合に非常に便利です。これにより、モデルとデータベース スキーマを一緒に迅速に進化させることができます。 ただし、欠点は、データベース内の既存のデータを失うことです。そのため、運用データベースでこのアプローチを使用 したくない ということです。 初期化子を使用して、テスト データを使用してデータベースを自動的にシード処理することは、多くの場合、アプリケーションを開発するための生産的な方法です。 Entity Framework データベース初期化子の詳細については、Tom Dykstra の mvc/Entity Framework チュートリアル ASP.NET 参照してください。
  2. モデル クラスに一致するように、既存のデータベースのスキーマを明示的に変更します。 この手法の長所は、データが維持されることです。 この変更は手動で行うことも、データベース変更スクリプトを作成して行うこともできます。
  3. Code First Migrations を使用して、データベース スキーマを更新します。

このチュートリアルでは、Code First Migrations を利用します。

新しい列の値を提供するように 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 、現在のムービー DB スキーマを使用して現在のムービー モデルを調べ、DB を新しいモデルに移行するために必要なコードを作成するように移行フレームワークに指示します。 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 に移動します。 新しい [評価] フィールドが表示されます。

4 つのムービーが一覧表示されている [M V C Movie Index] ページを示すスクリーンショット。

[ 新規作成 ] リンクをクリックして、新しいムービーを追加します。 評価を追加できることに注意してください。

7_CreateRioII

Create をクリックしてください。 評価を含む新しい映画が映画の一覧に表示されるようになりました。

7_ourNewMovie_SM

また、フィールドを Rating [編集]、[詳細]、[SearchIndex] ビュー テンプレートに追加する必要があります。

[パッケージ マネージャー コンソール] ウィンドウに "update-database" コマンドをもう一度入力しても、スキーマがモデルと一致するため、変更は行われません。

このセクションでは、モデル オブジェクトを変更し、データベースを変更と同期する方法について説明しました。 また、シナリオを試すことができるように、新しく作成したデータベースにサンプル データを設定する方法についても学習しました。 次に、モデル クラスに豊富な検証ロジックを追加し、一部のビジネス ルールを適用できるようにする方法を見てみましょう。