Entity Framework でモデル クラスを作成する (VB)
提供元: Microsoft
このチュートリアルでは、ASP.NET MVC と Microsoft Entity Framework を使用する方法について説明します。 Entity ウィザードを使って ADO.NET Entity Data Model を作成する方法を学習します。 このチュートリアルの過程で、Entity Framework を使ってデータベースのデータを選択、挿入、更新、削除する方法を示す Web アプリケーションを構築していきます。
このチュートリアルの目的は、ASP.NET MVC アプリケーションを構築するときに、Microsoft Entity Framework を使ってデータ アクセス クラスを作成する方法について説明することです。 このチュートリアルでは、Microsoft Entity Framework に関する予備知識は必要ありません。 このチュートリアルの終わりまでに、Entity Framework を使ってデータベース レコードを選択、挿入、更新、削除する方法を理解できます。
Microsoft Entity Framework は、データベースから自動的にデータ アクセス層を生成できるオブジェクト リレーショナル マッピング (O/RM) ツールです。 Entity Framework を使うことで、データ アクセス クラスを手動で作成する面倒な作業を回避できます。
Note
ASP.NET MVC と Microsoft Entity Framework の間に本質的なつながりはありません。 ASP.NET MVC で使用できる Entity Framework の代替手段はいくつかあります。 たとえば、Microsoft LINQ to SQL、NHibernate、SubSonic など、他の O/RM ツールを使って MVC モデル クラスを作成することができます。
ASP.NET MVC で Microsoft Entity Framework を使う方法を説明するために、簡単なサンプル アプリケーションを構築します。 ここでは、映画データベースのレコードを表示および編集できる映画データベース アプリケーションを作成します。
このチュートリアルでは、Service Pack 1 適用の Visual Studio 2008 または Visual Web Developer 2008 があることを前提としています。 Entity Framework を使用するには、Service Pack 1 が必要です。 次のアドレスから Visual Studio 2008 Service Pack 1 または Service Pack 1 適用の Visual Web Developer をダウンロードできます。
映画サンプル データベースの作成
映画データベース アプリケーションでは、次の列を含む Movies という名前のデータベース テーブルを使用します。
列名 | データ型 | Null を許容するか | 主キーか |
---|---|---|---|
Id | int | False | True |
Title | nvarchar(100) | False | False |
監督 | nvarchar(100) | False | False |
次の手順に従って、このテーブルを ASP.NET MVC プロジェクトに追加できます。
- ソリューション エクスプローラー ウィンドウで App_Data フォルダーを右クリックし、[追加]、[新規項目] メニュー オプションを選択します。
- [新しい項目の追加] ダイアログ ボックスから [SQL Server データベース] を選択し、データベースに MoviesDB.mdf という名前を付けて、[追加] ボタンをクリックします。
- MoviesDB.mdf ファイルをダブルクリックして、サーバー エクスプローラー/データベース エクスプローラー ウィンドウを開きます。
- MoviesDB.mdf のデータベース接続を展開し、Tables フォルダーを右クリックして、[新しいテーブルの追加] メニュー オプションを選択します。
- テーブル デザイナーで、Id、Title、Director の各列を追加します。
- [保存] ボタン (フロッピーのアイコン) をクリックして、Movies という名前の新しいテーブルを保存します。
Movies データベース テーブルを作成したら、いくつかのサンプル データをテーブルに追加する必要があります。 Movies テーブルを右クリックし、[テーブル データの表示] メニュー オプションを選択します。 表示されるグリッドに偽の映画データを入力できます。
ADO.NET Entity Data Model の作成
Entity Framework を使用するには、Entity Data Model を作成する必要があります。 Visual Studio の "Entity Data Model ウィザード" を利用して、データベースから自動的に Entity Data Model を生成できます。
次のステップを実行します。
- ソリューション エクスプローラー ウィンドウで Models フォルダーを右クリックし、[追加]、[新しい項目] メニュー オプションを選択します。
- [新しい項目の追加] ダイアログで、[データ] カテゴリを選択します (図 1 を参照)。
- [ADO.NET Entity Data Model] テンプレートを選択し、Entity Data Model に MoviesDBModel.edmx という名前を付けて、[追加] ボタンをクリックします。 [追加] ボタンをクリックすると、Data Model ウィザードが起動します。
- [モデルのコンテンツの選択] ステップで、[Generate from a database] (データベースから生成) オプションを選択し、[次へ] ボタンをクリックします (図 2 を参照)。
- [データ接続の選択] ステップで、MoviesDB.mdf のデータベース接続を選択し、MoviesDBEntities というエンティティ接続設定の名前を入力して、[次へ] ボタンをクリックします (図 3 を参照)。
- [データベース オブジェクトの選択] ステップで、Movie データベース テーブルを選択し、[完了] ボタンをクリックします (図 4 を参照)。
これらの手順を完了すると、ADO.NET Entity Data Model デザイナー (Entity デザイナー) が開きます。
図 1 – 新しい Entity Data Model の作成
図 2 – モデルのコンテンツの選択ステップ
図 3 – データ接続の選択
図 4 – データベース オブジェクトの選択
ADO.NET Entity Data Model の変更
Entity Data Model を作成した後は、Entity デザイナーを利用してモデルを変更できます (図 5 を参照)。 ソリューション エクスプローラー ウィンドウ内で Models フォルダーに含まれている MoviesDBModel.edmx ファイルをダブルクリックすれば、いつでも Entity デザイナーを開くことができます。
図 5 – ADO.NET Entity Data Model デザイナー
たとえば、Entity デザイナーを使って、Entity Model Data ウィザードが生成したクラスの名前を変更できます。 ウィザードによって、Movies という名前の新しいデータ アクセス クラスが作成されています。 つまり、ウィザードはクラスにデータベース テーブルとまったく同じ名前を付けています。 このクラスを使って特定の Movie インスタンスを表すので、このクラスの名前は Movies から Movie に変更する必要があります。
エンティティ クラスの名前を変更する場合は、Entity デザイナーでクラス名をダブルクリックし、新しい名前を入力します (図 6 を参照)。 または、Entity デザイナーでエンティティを選択した後、プロパティ ウィンドウでエンティティの名前を変更することもできます。
図 6 – エンティティ名の変更
変更を行った後、[保存] ボタン (フロッピー ディスクのアイコン) をクリックして Entity Data Model を保存することを忘れないでください。 バックグラウンドでは、Entity デザイナーが一連の Visual Basic .NET クラスを生成しています。 これらのクラスを表示するには、ソリューション エクスプローラー ウィンドウから MoviesDBModel.Designer.vb ファイルを開きます。
Designer.vb ファイル内のコードを変更しても、次回 Entity デザイナーを使用したときに上書きされるため、変更しないでください。 Designer.vb ファイルで定義されているエンティティ クラスの機能を拡張したい場合は、別のファイルに "部分クラス" を作成できます。
Entity Framework を使ったデータベース レコードの選択
映画レコードの一覧を表示するページの作成から、映画データベース アプリケーションの構築を開始しましょう。 リスト 1 の Home コントローラーでは、Index() という名前のアクションを公開します。 Index() アクションは、Entity Framework を利用して、Movie データベース テーブルのすべての映画レコードを返します。
リスト 1 – Controllers\HomeController.vb
<HandleError()> _
Public Class HomeController
Inherits System.Web.Mvc.Controller
Private _db As MoviesDBEntities
Public Sub New()
_db = New MoviesDBEntities()
End Sub
Public Function Index()
ViewData.Model = _db.MovieSet.ToList()
Return View()
End Function
End Class
リスト 1 のコントローラーにはコンストラクターが含まれていることがわかります。 このコンストラクターは、_db という名前のクラスレベルのフィールドを初期化します。 _db フィールドは、Microsoft Entity Framework によって生成されたデータベース エンティティを表します。 _db フィールドは、Entity デザイナーによって生成された MoviesDBEntities クラスのインスタンスです。
Index() アクション内で _db フィールドを使って、Movies データベース テーブルからレコードを取得します。 _db.MovieSet という式は、Movies データベース テーブルのすべてのレコードを表します。 ToList() メソッドを使って、映画のセットを Movie オブジェクトのジェネリック コレクションである List( Of Movie) に変換します。
映画レコードは、LINQ to Entities を使って取得します。 リスト 1 の Index() アクションでは、LINQ "メソッド構文" を使ってデータベース レコードのセットを取得しています。 または、代わりに LINQ "クエリ構文" を使うこともできます。 次の 2 つのステートメントは、まったく同じことを行っています。
ViewData.Model = _db.MovieSet.ToList()
ViewData.Model = (from m in _db.MovieSet select m).ToList()
自分にとって最もわかりやすい LINQ 構文 (メソッド構文またはクエリ構文) を使用してください。 2 つの方法にパフォーマンス上の違いはありません。スタイルが違うだけです。
リスト 2 のビューを使って、映画レコードを表示します。
リスト 2 - \Views\Home\Index.aspx
<%@ Page Language="VB"
Inherits="System.Web.Mvc.ViewPage(Of List(Of MvcApplication1.Movie))" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>Index</title>
</head>
<body>
<div>
<% For Each m In Model%>
Title: <%= m.Title %>
<br />
Director: <%= m.Director %>
<br />
<%=Html.ActionLink("Edit", "Edit", New With {.id = m.Id})%>
<%=Html.ActionLink("Delete", "Delete", New With {.id = m.Id})%>
<hr />
<% Next%>
<%= Html.ActionLink("Add Movie", "Add") %>
</div>
</body>
</html>
リスト 2 のビューには、各映画レコードを反復処理し、その映画レコードの Title および Director プロパティの値を表示する For Each ループが含まれています。 各レコードの横に [Edit] リンクと [Delete] リンクが表示されることに注意してください。 さらに、ビューの下部には [Add Movie] リンクが表示されます (図 7 を参照)。
図 7 – Index ビュー
Index ビューは "型指定されたビュー" です。 Index ビューには、Inherits 属性が含まれている <%@ Page %> ディレクティブがあります。 Inherits 属性は、ViewData.Model プロパティを、Movie オブジェクトの厳密に型指定されたジェネリック リスト コレクションの List(Of Movie) にキャストします。
Entity Framework を使ったデータベース レコードの挿入
Entity Framework を使って、データベース テーブルに新しいレコードを簡単に挿入できます。 リスト 3 には、Home コントローラー クラスに追加される 2 つの新しいアクションが含まれています。これを使って、Movie データベース テーブルに新しいレコードを挿入することができます。
リスト 3 – Controllers\HomeController.vb (Add メソッド)
<HandleError()> _
Public Class HomeController
Inherits System.Web.Mvc.Controller
Public Function Add()
Return View()
End Function
<AcceptVerbs(HttpVerbs.Post)> _
Public Function Add(ByVal form As FormCollection)
Dim movieToAdd As New Movie()
' Deserialize (Include white list!)
TryUpdateModel(movieToAdd, New String() {"Title", "Director"}, form.ToValueProvider())
' Validate
If String.IsNullOrEmpty(movieToAdd.Title) Then
ModelState.AddModelError("Title", "Title is required!")
End If
If String.IsNullOrEmpty(movieToAdd.Director) Then
ModelState.AddModelError("Director", "Director is required!")
End If
' If valid, save movie to database
If (ModelState.IsValid) Then
_db.AddToMovieSet(movieToAdd)
_db.SaveChanges()
Return RedirectToAction("Index")
End If
' Otherwise, reshow form
Return View(movieToAdd)
End Function
End Class
最初の Add() アクションは、単にビューを返します。 このビューには、新しい映画データベース レコードを追加するためのフォームが含まれています (図 8 を参照)。 フォームを送信すると、2 番目の Add() アクションが呼び出されます。
2 番目の Add() アクションは AcceptVerbs 属性で修飾されていることに注意してください。 このアクションは、HTTP POST 操作を実行するときにのみ呼び出すことができます。 つまり、このアクションは HTML フォームを投稿するときにのみ呼び出すことができます。
2 番目の Add() アクションは、ASP.NET MVC TryUpdateModel() メソッドを使って Entity Framework Movie クラスの新しいインスタンスを作成します。 TryUpdateModel() メソッドは、Add() メソッドに渡された FormCollection のフィールドを受け取り、これらの HTML フォーム フィールドの値を Movie クラスに代入します。
Entity Framework を使う場合は、TryUpdateModel メソッドまたは UpdateModel メソッドを使ってエンティティ クラスのプロパティを更新するときに、プロパティの "セーフリスト" を指定する必要があります。
次に、Add() アクションはいくつかの簡単なフォーム検証を実行します。 Title プロパティと Director プロパティの両方が値を持っていることを確認します。 検証エラーがある場合は、ModelState に検証エラー メッセージが追加されます。
検証エラーがない場合は、Entity Framework を使って Movies データベース テーブルに新しい映画レコードが追加されます。 この新しいレコードは、次の 2 行のコードでデータベースに追加されます。
_db.AddToMovieSet(movieToAdd)
_db.SaveChanges()
最初のコード行は、Entity Framework によって追跡されている映画のセットに新しい Movie エンティティを追加します。 2 番目のコード行は、追跡されている Movies に対して行われたすべての変更を基になるデータベースに保存します。
図 8 – Add ビュー
Entity Framework を使ったデータベース レコードの更新
新しいデータベース レコードを挿入したときとほぼ同じ方法で、Entity Framework を使ってデータベース レコードを編集することができます。 リスト 4 には、Edit() という名前の 2 つの新しいコントローラー アクションが含まれています。 最初の Edit() アクションは、映画レコードを編集するための HTML フォームを返します。 2 番目の Edit() アクションは、データベースの更新を試みます。
リスト 4 – Controllers\HomeController.vb (Edit メソッド)
<HandleError()> _
Public Class HomeController
Inherits System.Web.Mvc.Controller
Public Function Edit(ByVal id As Integer)
' Get movie to update
Dim movieToUpdate As Movie = _db.MovieSet.First(Function(m) m.Id = id)
ViewData.Model = movieToUpdate
Return View()
End Function
<AcceptVerbs(HttpVerbs.Post)> _
Public Function Edit(ByVal form As FormCollection)
' Get movie to update
Dim id As Integer = Integer.Parse(form("id"))
Dim movieToUpdate As Movie = _db.MovieSet.First(Function(m) m.Id = id)
' Deserialize (Include white list!)
TryUpdateModel(movieToUpdate, New String() {"Title", "Director"}, form.ToValueProvider)
' Validate
If String.IsNullOrEmpty(movieToUpdate.Title) Then
ModelState.AddModelError("Title", "Title is required!")
End If
If String.IsNullOrEmpty(movieToUpdate.Director) Then
ModelState.AddModelError("Director", "Director is required!")
End If
' If valid, save movie to database
If (ModelState.IsValid) Then
_db.SaveChanges()
Return RedirectToAction("Index")
End If
' Otherwise, reshow form
Return View(movieToUpdate)
End Function
End Class
2 番目の Edit() アクションでは、まず編集する映画の Id と一致する Movie レコードをデータベースから取得します。 次の LINQ to Entities ステートメントは、特定の Id と一致する最初のデータベース レコードを取得します。
Dim movieToUpdate As Movie = _db.MovieSet.First(Function(m) m.Id = id)
次に、TryUpdateModel() メソッドを使って、HTML フォーム フィールドの値を Movie エンティティのプロパティに代入します。 セーフリストを指定してどのプロパティを更新するか厳密に指定していることに注意してください。
次に、いくつかの簡単な検証を実行して、Movie の Title プロパティと Director プロパティの両方が値を持っていることを確認します。 いずれかのプロパティが値を持っていない場合は、ModelState に検証エラー メッセージが追加され、ModelState.IsValid は false 値を返します。
最後に、検証エラーがなかった場合は、SaveChanges() メソッドを呼び出して基になる Movies データベース テーブルを変更内容で更新します。
データベース レコードを編集するときは、編集するレコードの Id をデータベースの更新を実行するコントローラー アクションに渡す必要があります。 そうでないと、コントローラー アクションには基になるデータベースのどのレコードを更新するかがわかりません。 リスト 5 の Edit ビューには、編集しているデータベース レコードの Id を表す非表示のフォーム フィールドが含まれています。
リスト 5 – Views\Home\Edit.aspx
<%@ Page Language="VB" Inherits="System.Web.Mvc.ViewPage(Of MvcApplication1.Movie)" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head id="Head1" runat="server">
<title>Edit</title>
<style type="text/css">
.input-validation-error
{
background-color:Yellow;
}
</style>
</head>
<body>
<div>
<h1>Edit Movie</h1>
<form method="post" action="/Home/Edit">
<!-- Include Hidden Id -->
<%= Html.Hidden("id") %>
Title:
<br />
<%= Html.TextBox("title") %>
<br /><br />
Director:
<br />
<%= Html.TextBox("director") %>
<br /><br />
<input type="submit" value="Edit Movie" />
</form>
</div>
</body>
</html>
Entity Framework を使ったデータベース レコードの削除
このチュートリアルで取り組む最後のデータベース操作は、データベース レコードを削除することです。 リスト 6 のコントローラー アクションを使って、特定のデータベース レコードを削除できます。
リスト 6 -- \Controllers\HomeController.vb (Delete アクション)
<HandleError()> _
Public Class HomeController
Inherits System.Web.Mvc.Controller
Public Function Delete(ByVal id As Integer)
' Get movie to delete
Dim movieToDelete As Movie = _db.MovieSet.First(Function(m) m.Id = id)
' Delete
_db.DeleteObject(movieToDelete)
_db.SaveChanges()
' Show Index view
Return RedirectToAction("Index")
End Function
End Class
Delete() アクションでは、まずアクションに渡された Id と一致する Movie エンティティを取得します。 次に、DeleteObject() メソッドとその後に SaveChanges() メソッドを呼び出して、データベースからその映画を削除します。 最後に、ユーザーを Index ビューにリダイレクトします。
まとめ
このチュートリアルの目的は、ASP.NET MVC と Microsoft Entity Framework を利用してデータベース駆動型 Web アプリケーションを構築する方法を示すことでした。 データベース レコードの選択、挿入、更新、削除を実行できるアプリケーションの構築方法を学習しました。
最初に、Entity Data Model ウィザードを使って Visual Studio 内から Entity Data Model を生成する方法について説明しました。 次に、LINQ to Entities を使ってデータベース テーブルから一連のデータベース レコードを取得する方法を学習しました。 最後に、Entity Framework を使ってデータベース レコードの挿入、更新、削除を行いました。