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

作成者: Rick Anderson

このチュートリアルでは、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 の前提条件のリンクをクリックして、前提条件をインストールします。

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

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

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

まず、新しい Rating プロパティを既存の Movie クラスに追加します。 Movie.cs ファイルを開き、次のように Rating プロパティを追加します。

Public Property Rating() As String

完成した Movie クラスは次のコードのようになります。

Public Class Movie
    Public Property ID() As Integer
    Public Property Title() As String
    Public Property ReleaseDate() As Date
    Public Property Genre() As String
    Public Property Price() As Decimal
    Public Property Rating() As String
End Class

[デバッグ]>[Build Movie] メニュー コマンドを使用してアプリケーションを再コンパイルします。

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

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

<table>
    <tr>
        <th>            Title        </th>
        <th>            ReleaseDate        </th>
        <th>            Genre        </th>
        <th>            Price        </th>
        <th>Rating</th>
        <th></th>
    </tr>

@For Each item In Model
    Dim currentItem = item
    @<tr>
        <td>
            @Html.DisplayFor(Function(modelItem) currentItem.Title)
        </td>
        <td>
            @Html.DisplayFor(Function(modelItem) currentItem.ReleaseDate)
        </td>
        <td>
            @Html.DisplayFor(Function(modelItem) currentItem.Genre)
        </td>
        <td>
            @Html.DisplayFor(Function(modelItem) currentItem.Price)
        </td>
         <td>
            @Html.DisplayFor(Function(modelItem) currentItem.Rating)
        </td>
        <td>
            @Html.ActionLink("Edit", "Edit", New With {.id = currentItem.ID}) |
            @Html.ActionLink("Details", "Details", New With {.id = currentItem.ID}) |
            @Html.ActionLink("Delete", "Delete", New With {.id = currentItem.ID})
        </td>
    </tr>
Next

</table>

次に、\Views\Movies\Create.vbhtml ファイルを開き、フォームの末尾付近に次のマークアップを追加します。 これによってテキスト ボックスがレンダリングされ、新しいムービーが作成されたときに評価を指定できるようになります。

<div class="editor-label">
     @Html.LabelFor(Function(model) model.Rating)
 </div>
 <div class="editor-field">
     @Html.EditorFor(Function(model) model.Rating)
     @Html.ValidationMessageFor(Function(model) model.Rating)
 </div>

モデルとデータベース スキーマの差異の管理

アプリケーション コードを、新しい Rating プロパティをサポートするように更新しました。

ここで、アプリケーションを実行し、/Movies URL にアクセスします。 ただし、アクセスすると次のエラーが表示されます。

Screenshot that shows a browser window with an error that states Server Error in Application.

このエラーが表示されるのは、更新された Movie モデル クラスが既存のデータベースの Movie テーブルのスキーマと異なるためです。 (データベース テーブルに Rating 列はありません)。

このチュートリアルの前の方でしたように、Entity Framework の Code First を使用してデータベースを自動作成すると、既定で Code First がテーブルをデータベースに追加して、データベースのスキーマがその生成元であるモデル クラスと同期されているかを追跡するようになります。 もし同期されていない場合、Entity Framework はエラーをスローします。 これにより、実行時にあいまいなエラーが表示されて初めて気づくような問題を、開発段階で容易に追跡できるようになります。 先ほど表示されたエラー メッセージは、この同期チェック機能によるものです。

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

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

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

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

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

Note

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

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

Screenshot that shows the Solution Explorer window. Add is selected in the Models right click menu and Class is selected in the sub menu.

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

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

Namespace MvcMovie.Models
    Public Class MovieInitializer
        Inherits DropCreateDatabaseIfModelChanges(Of MovieDBContext)
        Protected Overrides Sub Seed(ByVal context As MovieDBContext)
            Dim movies = New List(Of Movie) From {
             New Movie With {.Title = "When Harry Met Sally", .ReleaseDate = Date.Parse("1989-1-11"), .Genre = "Romantic Comedy", .Rating = "R", .Price = 7.99D},
             New Movie With {.Title = "Ghostbusters ", .ReleaseDate = Date.Parse("1984-3-13"), .Genre = "Comedy", .Rating = "R", .Price = 8.99D},
             New Movie With {.Title = "Ghostbusters 2", .ReleaseDate = Date.Parse("1986-2-23"), .Genre = "Comedy", .Rating = "R", .Price = 9.99D},
             New Movie With {.Title = "Rio Bravo", .ReleaseDate = Date.Parse("1959-4-15"), .Genre = "Western", .Rating = "R", .Price = 3.99D}}

            movies.ForEach(Function(d) context.Movies.Add(d))
        End Sub
    End Class
End Namespace

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

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

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

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

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

Sub Application_Start()
        System.Data.Entity.Database.SetInitializer(Of MovieDBContext)(New MvcMovie.Models.MovieInitializer())
       
        AreaRegistration.RegisterAllAreas()

        RegisterGlobalFilters(GlobalFilters.Filters)
        RegisterRoutes(RouteTable.Routes)
    End Sub

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

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

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

7_MyMovieList_SM

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

7_CreateRioII

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

7_ourNewMovie_SM

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