新しいフィールドの追加
作成者 : Rick Anderson
Note
このチュートリアルの更新バージョンは、Visual Studio の最新バージョンを使用してこちらで入手できます。 新しいチュートリアルでは、mvc ASP.NET Coreを使用します。これにより、このチュートリアルに対して多くの機能強化が提供されます。
このチュートリアルでは、ASP.NET Core MVC のコントローラーとビューについて説明します。 Razor Pages は、ASP.NET Coreの新しい代替手段であり、Web UI の構築を容易かつ生産的にするページ ベースのプログラミング モデルです。 MVC バージョンの前に Razor Pages チュートリアルを試してみることをお勧めします。 この Razor ページのチュートリアルの特徴は次のとおりです。
- 使いやすい。
- 多くの機能をカバーしている。
- 新しいアプリ開発に推奨されるアプローチです。
このセクションでは、Entity Framework Code First Migrationsを使用して、変更がデータベースに適用されるように、いくつかの変更をモデル クラスに移行します。
既定では、このチュートリアルで前述したように、Entity Framework Code First を使用してデータベースを自動的に作成すると、Code First はデータベースにテーブルを追加して、データベースのスキーマが生成元のモデル クラスと同期しているかどうかを追跡するのに役立ちます。 同期されていない場合、Entity Framework はエラーをスローします。 これにより、開発時の問題を簡単に追跡できます。そうしないと、実行時にのみ見つかる可能性がある (あいまいなエラーによって) 可能性があります。
モデル変更のCode First Migrationsの設定
[ソリューション エクスプローラー] に移動します。 Movies.mdf ファイルを右クリックし、[削除] を選択して movies データベースを削除します。 Movies.mdf ファイルが表示されない場合は、赤いアウトラインで下に示す [すべてのファイルを表示] アイコンをクリックします。
アプリケーションをビルドしてエラーがないことを確認します。
[ツール] メニューの [NuGet パッケージ マネージャー] をクリックし、[パッケージ マネージャー コンソール] をクリックします。
プロンプトの [ パッケージ マネージャー コンソール ] ウィンドウで、「 PM>
」と入力します。
Enable-Migrations -ContextTypeName MvcMovie.Models.MovieDBContext
Enable-Migrations コマンド (上記) は、新しい Migrations フォルダーに Configuration.cs ファイルを作成します。
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 の使用] をクリックします。
これにより、次の using ステートメントが追加されます。
using MvcMovie.Models;
Note
Code First Migrationsは、移行のたびに メソッドを呼び出Seed
します (つまり、パッケージ マネージャー コンソールで 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、Migrations フォルダーに別のクラス ファイル ({DateStamp}_Initial.cs) を作成します。このクラスには、データベース スキーマを作成するコードが含まれています。 移行のファイル名の先頭には、並べ替えに役立つタイムスタンプが付きます。 {DateStamp}_Initial.cs ファイルを調べます。これには、Movie DB のテーブルを作成Movies
する手順が含まれています。 次の手順でデータベースを更新すると、この {DateStamp}_Initial.cs ファイルが実行され、DB スキーマが作成されます。 次に、 Seed メソッドが実行され、テスト データが DB に設定されます。
パッケージ マネージャー コンソールで、 コマンドupdate-database
を入力してデータベースを作成し、 メソッドを実行しますSeed
。
テーブルが既に存在し、作成できないことを示すエラーが発生する場合は、データベースを削除した後、および を実行する前にアプリケーションを実行したため update-database
である可能性があります。 その場合は、 Movies.mdf ファイルをもう一度削除し、コマンドを update-database
再試行します。 それでもエラーが発生する場合は、migrations フォルダーとコンテンツを削除し、このページの上部にある手順から開始します (つまり、 Movies.mdf ファイルを削除してから、Enable-Migrations に進みます)。 それでもエラーが発生する場合は、SQL Server オブジェクト エクスプローラー開き、一覧からデータベースを削除します。 ".mdf ファイルをデータベースとしてアタッチできません" というエラーが表示された場合は、 web.config ファイルの接続文字列の一部として Initial Catalog プロパティを削除します。
アプリケーションを実行し、 /Movies URL に移動します。 シード データが表示されます。
ムービー モデルへの評価プロパティの追加
まず、既存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; }
}
アプリケーションをビルドします (Ctrl + Shift + B)。
クラスに新しいフィールドを Movie
追加したので、この新しいプロパティが含まれるようにバインド 許可リスト も更新する必要があります。 および アクション メソッドの bind
Create
Edit
属性を更新して、 プロパティを 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 Migrations を使用したデータベースの更新を検討してください (https://go.microsoft.com/fwlink/?LinkId=238269)。
アプリケーションの更新 Movie
されたモデル クラスが既存のデータベースのテーブルのスキーマと異なるため、このエラーが Movie
表示されます。 (データベース テーブルに Rating
列はありません)。
このエラーを解決するための手法がいくつかあります。
- Entity Framework に、新しいモデル クラス スキーマに基づいてデータベースを自動的にドロップさせ、再作成させます。 この手法は、開発周期の早い段階で、テスト データベースで開発しているときに非常に便利です。モデルとデータベース スキーマを一緒に短期間で発展させることができます。 ただし、欠点は、データベース内の既存のデータを失うので、運用データベースではこの方法を使用 したくない ということです。 初期化子を利用し、データベースにテスト データを自動的に初期投入します。多くの場合、アプリケーション開発の手法として有益な方法です。 Entity Framework データベース初期化子の詳細については、 MVC/Entity Framework のチュートリアル ASP.NET 参照してください。
- モデル クラスに一致するように、既存のデータベースのスキーマを明示的に変更します。 この手法の長所は、データが維持されることです。 この変更は手動で行うことも、データベース変更スクリプトを作成して行うこともできます。
- 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 = "PG",
Price = 7.99M
},
ソリューションをビルドし、[ パッケージ マネージャー コンソール ] ウィンドウを開き、次のコマンドを入力します。
add-migration Rating
コマンドは add-migration
、現在のムービー DB スキーマを使用して現在のムービー モデルを調べ、DB を新しいモデルに移行するために必要なコードを作成するように移行フレームワークに指示します。 Rating という名前は任意であり、移行ファイルに名前を付けるために使用されます。 移行手順にわかりやすい名前を使用すると便利です。
このコマンドが完了すると、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 に移動します。 新しい [評価] フィールドが表示されます。
[ 新規作成 ] リンクをクリックして、新しいムービーを追加します。 評価を追加できることに注意してください。
Create をクリックしてください。 評価を含む新しい映画が、映画の一覧に表示されるようになりました。
プロジェクトで移行が使用されたので、新しいフィールドを追加したり、スキーマを更新したりするときにデータベースを削除する必要はありません。 次のセクションでは、スキーマをさらに変更し、移行を使用してデータベースを更新します。
また、フィールドを Rating
[編集]、[詳細]、[削除] の各ビュー テンプレートに追加する必要があります。
スキーマがモデルと一致するため、 パッケージ マネージャー コンソール ウィンドウに "update-database" コマンドをもう一度入力しても、移行コードは実行されません。 ただし、"update-database" を実行するとメソッドが再度実行 Seed
され、Seed データのいずれかを変更した場合、メソッドによってデータがアップサートされるため Seed
、変更は失われます。 メソッドの Seed
詳細については、Tom Dykstra の MVC /Entity Framework チュートリアル ASP.NET 人気があります。
このセクションでは、モデル オブジェクトを変更し、データベースを変更と同期する方法について説明しました。 また、シナリオを試すことができるように、新しく作成されたデータベースにサンプル データを設定する方法についても学習しました。 これは、Code First の簡単な概要でした。このテーマに関するより完全なチュートリアルについては、「 ASP.NET MVC アプリケーション用の Entity Framework データ モデルの作成 」を参照してください。 次に、モデル クラスに高度な検証ロジックを追加し、一部のビジネス ルールを適用できるようにする方法を見てみましょう。
フィードバック
フィードバックの送信と表示