次の方法で共有


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

作成者: Rick Anderson

Note

ASP.NET MVC 5 と Visual Studio 2013 を使用するこのチュートリアルの更新版は、こちらで入手できます。 より安全で、より簡単に操作でき、より多くの機能を備えています。

このチュートリアルでは、Microsoft Visual Web Developer 2010 Express Service Pack 1 (Microsoft Visual Studio の無料版) を使用した ASP.NET MVC Web アプリケーション構築の基本事項を説明します。 開始する前に、以下に示す前提条件がインストールされていることを確認してください。 次のリンクをクリックすると、これらをすべてインストールできます: Web Platform Installer。 また、次のリンクを使用して前提条件となるソフトウェアを個別にインストールすることもできます。

Visual Web Developer 2010 ではなく Visual Studio 2010 を使用する場合は、Visual Studio 2010 の前提条件のリンクをクリックして、前提条件をインストールします。

このトピックに関連する、Visual Web Developer プロジェクトと C# ソース コードを使用できます。 C# バージョンをダウンロードします。 Visual Basic を使用する場合は、このチュートリアルの Visual Basic バージョンに切り替えてください。

このセクションでは、モデル クラスをいくらか変更し、モデルの変更に合わせてデータベース スキーマを更新する方法について学びます。

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

まず、新しい Rating プロパティを既存の Movie クラスに追加します。 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] メニュー コマンドを使用してアプリケーションを再コンパイルします。

Model クラスを更新したので、\Views\Movies\Index.cshtml\Views\Movies\Create.cshtml のビュー テンプレートを更新して、新しい Rating プロパティをサポートする必要があります。

\Views\Movies\Index.cshtml ファイルを開き、<th>Rating</th> 列見出しを Price 列の直後に追加します。 次に、@item.Rating 値をレンダリングするために、テンプレートの末尾付近に <td> 列を追加します。 更新した Index.cshtml ビュー テンプレートは次のようになります。

<table>
    <tr>
        <th></th>
        <th>Title</th>
        <th>Release Date</th>
        <th>Genre</th>
        <th>Price</th>
        <th>Rating</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 Me", "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 の Code First を使用してデータベースを自動作成すると、既定で Code First がテーブルをデータベースに追加して、データベースのスキーマがその生成元であるモデル クラスと同期されているかを追跡するようになります。 もし同期されていない場合、Entity Framework はエラーをスローします。 これにより、実行時にあいまいなエラーが表示されて初めて気づくような問題を、開発段階で容易に追跡できるようになります。 先ほど表示されたエラー メッセージは、この同期チェック機能によるものです。

このエラーは 2 つの方法で解決できます。

  1. Entity Framework に、新しいモデル クラス スキーマに基づいてデータベースを自動的にドロップさせ、再作成させます。 この方法では、モデルとデータベース スキーマの両方を迅速に改善できるため、テスト用データベースでアクティブに開発を行っている場合に非常に便利です。 ただし欠点もあり、データベースの既存データが失われます。実稼働データベースではこの手法は推奨されません
  2. モデル クラスに一致するように、既存のデータベースのスキーマを明示的に変更します。 この手法の長所は、データが維持されることです。 この変更は手動で行うことも、データベース変更スクリプトを作成して行うこともできます。

このチュートリアルでは最初の方法を使用して、モデルが変更されるたびに Entity Framework の Code First が自動でデータベースを再作成するようにします。

モデルの変更時にデータベースを自動的に再作成する

アプリケーションのモデルを変更するたびに Code First がデータベースを削除して再作成するようにアプリケーションを更新しましょう。

Note

警告 データベースを自動的に削除して再作成するこの方法は、開発またはテスト用データベースを使用している場合にだけ採用し、実際のデータを含む実稼働データベースでは絶対に採用しないでください。 運用サーバーで使用すると、データが失われる恐れがあります。

ソリューション エクスプローラーModels フォルダーを右クリックし、[追加][クラス] の順に選択します。

ソリューション エクスプローラー ウィンドウを示すスクリーンショット。[モデル] 右クリック メニューで [追加] が選択されています。サブメニューで [クラス] が選択されています。

「MovieInitializer」という名前を付けます。 MovieInitializer クラスを更新して、次のコードを含めます。

using System;
using System.Collections.Generic;
using System.Data.Entity;

namespace MvcMovie.Models {
    public class MovieInitializer : DropCreateDatabaseIfModelChanges<MovieDBContext> {
        protected override void Seed(MovieDBContext context) {
            var movies = new List<Movie> {  
  
                 new Movie { Title = "When Harry Met Sally",   
                             ReleaseDate=DateTime.Parse("1989-1-11"),   
                             Genre="Romantic Comedy",  
                             Rating="R",  
                             Price=7.99M},  

                     new Movie { Title = "Ghostbusters ",   
                             ReleaseDate=DateTime.Parse("1984-3-13"),   
                             Genre="Comedy",  
                              Rating="R",  
                             Price=8.99M},   
  
                 new Movie { Title = "Ghostbusters 2",   
                             ReleaseDate=DateTime.Parse("1986-2-23"),   
                             Genre="Comedy",  
                             Rating="R",  
                             Price=9.99M},   

               new Movie { Title = "Rio Bravo",   
                             ReleaseDate=DateTime.Parse("1959-4-15"),   
                             Genre="Western",  
                             Rating="R",  
                             Price=3.99M},   
             };

            movies.ForEach(d => context.Movies.Add(d));
        }
    }
}

MovieInitializer クラスは、モデル クラスが変更された場合に、モデルが使用するデータベースを削除して自動で再作成することを定義します。 コードには、データベースが作成 (または再作成) されるたびに自動的に追加される、いくつかの既定のデータを指定する Seed メソッドが含まれています。 これは、データベースにいくらかのサンプル データを入力するための便利な方法です。モデルを変更するたびに手動でそれらを入力する必要はありません。

MovieInitializer クラスの定義が完了したので、アプリケーションを実行するたびにモデル クラスがデータベースのスキーマと異なっているかを確認するために、このクラスを関連付けましょう。 異なっている場合は、初期化子を実行してデータベースを作成してモデルを一致させ、データベースにサンプル データを入力します。

MvcMovies プロジェクトのルートにある Global.asax ファイルを開きます。

[グローバル ドット asax dot c s] タブを示すスクリーンショット。グローバルドットアサックスは、ソリューション エクスプローラーウィンドウで赤で囲まれています。

Global.asax ファイルには、プロジェクトのアプリケーション全体を定義するクラスと、アプリケーションが最初に起動されたときに実行される Application_Start イベント ハンドラーが含まれています。

ファイルの先頭に 2 つの using ステートメントを追加しましょう。 1 番目は Entity Framework 名前空間を参照し、2 番目は MovieInitializer クラスが存在する名前空間を参照します。

using System.Data.Entity;            // Database.SetInitialize
using MvcMovie.Models;              // MovieInitializer

次に、Application_Start メソッドを見つけて、以下のように、メソッドの先頭に Database.SetInitializer への呼び出しを追加します。

protected void Application_Start()
{
    Database.SetInitializer<MovieDBContext>(new MovieInitializer());

    AreaRegistration.RegisterAllAreas();
    RegisterGlobalFilters(GlobalFilters.Filters);
    RegisterRoutes(RouteTable.Routes);
}

今追加した Database.SetInitializer ステートメントは、スキーマとデータベースが一致しない場合、MovieDBContext インスタンスが使用するデータベースを自動的に削除して再作成する必要があることを示しています。 また既に説明したように、MovieInitializer クラスで指定されているサンプル データをデータベースに入力します。

Global.asax ファイルを閉じます。

アプリケーションを再実行し、/Movies URL にアクセスします。 アプリケーションが起動すると、モデル構造がデータベース スキーマと一致しないことが検出されます。 新しいモデル構造に一致するようにデータベースが自動的に再作成され、データベースにサンプル ムービーが入力されます。

7_MyMovieList_SM

[Create New] リンクをクリックして、新しい映画を追加します。 評価も追加できます。

7_CreateRioII

Create をクリックしてください。 評価を含む新しいムービーが、ムービー一覧に表示されます。

7_ourNewMovie_SM

このセクションでは、モデル オブジェクトを変更し、データベースをその変更に合わせて同期させる方法を学びました。 また、新しく作成されたデータベースにサンプル データを入力してシナリオを試してみる方法についても学習しました。 次に、モデル クラスに高度な検証ロジックを追加して、ビジネス ルールを適用できるようにする方法を学びましょう。