Entity Framework 4.0 の新機能
著者: Tom Dykstra
このチュートリアル シリーズは、Entity Framework の概要チュートリアル シリーズで作成された Contoso University Web アプリケーションをベースとしています。 前のチュートリアルを終わらせていない場合は、このチュートリアルの始めに、前のチュートリアルで作成するはずであったアプリケーションをダウンロードできます。 完了したチュートリアル シリーズで作成されたアプリケーションをダウンロードすることもできます。 チュートリアルに関する質問がある場合は、ASP.NET Entity Framework フォーラムに質問を投稿できます。
前のチュートリアルでは、Entity Framework を使用する Web アプリケーションのパフォーマンスを最大化するためのいくつかの方法について説明しました。 このチュートリアルでは、Entity Framework のバージョン 4 で最も重要となる新機能についていくつか確認し、すべての新機能のより完全な概要を提供するリソースへのリンクを提供します。 このチュートリアルで注目する機能は次のとおりです。
- 外部キーの関連付け。
- ユーザー定義 SQL コマンドの実行。
- Model-First 開発。
- POCO サポート。
さらに、このチュートリアルでは、Entity Framework の次のリリースで提供される予定の "Code-First 開発"についても簡単に説明します。
チュートリアルを開始するには、Visual Studio を起動し、前のチュートリアルで使用していた Contoso University Web アプリケーションを開きます。
外部キーの関連付け
Entity Framework のバージョン 3.5 にはナビゲーション プロパティが含まれていましたが、データ モデルに外部キー プロパティが含まれていませんでした。 たとえば、StudentGrade
テーブルの CourseID
列と StudentID
列は StudentGrade
エンティティには含まれていません。
このアプローチの理由は、厳密に言えば外部キーが物理的な実装の一部であり、概念的なデータ モデルではないからです。 ただし、実際には、外部キーに直接アクセスできればコード内のエンティティを簡単に操作できます。
データ モデルで外部キーを使用してコードを簡略化する方法の例では、外部キーを使用せずに DepartmentsAdd.aspx ページをコーディングした場合の方法について考えるといいでしょう。 Department
エンティティでは、Administrator
プロパティは Person
エンティティの PersonID
に対応する外部キーです。 新しい部署とその管理者との関連付けを確立するために必要なことは、次のようにデータバインド コントロールの ItemInserting
イベント ハンドラーで Administrator
プロパティの値を設定することでした。
protected void DepartmentsDetailsView_ItemInserting(object sender, DetailsViewInsertEventArgs e)
{
e.Values["Administrator"] = administratorsDropDownList.SelectedValue;
}
データ モデルに外部キーがない場合は、データバインド コントロールの Inserting
イベントではなく、データ ソース コントロールの ItemInserting
イベントを処理して、エンティティがエンティティ セットに追加される前にエンティティ自体への参照を取得していました。 その参照があれば、次の例のようなコードを使用して関連付けを確立できます。
departmentEntityToBeInserted.PersonReference.EntityKey = new System.Data.EntityKey("SchoolEntities.Departments", "PersonID", Convert.ToInt32(administratorsDropDownList.SelectedValue));
departmentEntityToBeInserted.Person = context.People.Single(p => p.PersonID == Convert.ToInt32(administratorsDropDownList.SelectedValue));
Entity Framework チームの外部キーの関連付けに関するブログ投稿からわかるように、コードの複雑さの違いがはるかに大きい場合もあります。 概念的なデータ モデルで実装の一部を使用してコードを簡素化することを好むユーザーのニーズを満たすため、Entity Framework では、データ モデルに外部キーを含めるオプションが提供されるようになりました。
Entity Framework の用語では、データ モデルに外部キーを含めることを "外部キーの関連付け" と言い、外部キーを除外する場合は "独立した関連付け" と呼んでいます。
ユーザー定義 SQL コマンドの実行
以前のバージョンの Entity Framework では、独自の SQL コマンドをすぐに作成して実行するような簡単な方法はなく、 Entity Framework で SQL コマンドを動的に生成するか、ストアド プロシージャを作成して関数としてインポートする必要がありました。 バージョン 4 では、ExecuteStoreQuery
メソッドと ExecuteStoreCommand
メソッドが ObjectContext
クラスに追加されたため、任意のクエリをデータベースに直接渡しやすくなります。
Contoso University の管理者が、ストアド プロシージャを作成してデータ モデルにインポートするプロセスを経ることなく、データベースで一括変更を実行できるようにしたいと考えているとします。 最初に、ページでデータベース内のすべてのコースのクレジット数を変更できるように要求されます。 Web ページでは、すべての Course
行の Credits
列の値を乗算するために使用する数値を入力できるようにしたいと考えています。
Site.Master マスター ページを使用するページを新規作成し、「UpdateCredits.aspx」 という名前を付けます。 次に、次のマークアップを Content2
という名前の Content
コントロールに追加します。
<h2>Update Credits</h2>
Enter the number to multiply the current number of credits by:
<asp:TextBox ID="CreditsMultiplierTextBox" runat="server"></asp:TextBox>
<br /><br />
<asp:Button ID="ExecuteButton" runat="server" Text="Execute" OnClick="ExecuteButton_Click" /><br /><br />
Rows affected:
<asp:Label ID="RowsAffectedLabel" runat="server" Text="0" ViewStateMode="Disabled"></asp:Label><br /><br />
このマークアップによって、ユーザーが乗数の値を入力できる TextBox
コントロール、コマンドを実行するためにクリックする Button
コントロール、および影響を受ける行数を示す Label
コントロールが作成されます。
UpdateCredits.aspx.cs を開き、次の using
ステートメントと、ボタンの Click
イベントのハンドラーを追加します。
using ContosoUniversity.DAL;
protected void ExecuteButton_Click(object sender, EventArgs e)
{
using (SchoolEntities context = new SchoolEntities())
{
RowsAffectedLabel.Text = context.ExecuteStoreCommand("UPDATE Course SET Credits = Credits * {0}", CreditsMultiplierTextBox.Text).ToString();
}
}
このコードでは、テキスト ボックスの値を使用して SQL Update
コマンドを実行し、ラベルを使用して影響を受ける行の数を表示します。 ページを実行する前に、Courses.aspx ページを実行して、データの "前" の画像を取得します。
UpdateCredits.aspx を実行し、乗数に「10」と入力してから [実行] をクリックします。
Courses.aspx ページをもう一度実行して、変更されたデータを確認します。
(クレジットの数を元の値に戻す場合は、UpdateCredits.aspx.cs で Credits * {0}
を Credits / {0}
に変更し、除数に「10」と入力してからページを再実行します。)
コードで定義するクエリの実行の詳細については、「方法: データ ソースに対してコマンドを直接実行する」を参照してください。
Model-First 開発
これらのチュートリアルでは、まずデータベースを作成し、次にデータベースの構造に基づいてデータ モデルを生成しました。 Entity Framework 4 では、代わりにデータ モデルから開始し、次にデータ モデルの構造に基づいてデータベースを生成できます。 データベースがまだ存在しないアプリケーションを作成する場合でも、モデル優先のアプローチによって、物理的な実装の詳細を気にすることなく、アプリケーションにとって概念的に意味のあるエンティティとリレーションシップを作成できます (ただし、これは開発の初期段階でのみ当てはまります。最終的にデータベースが作成され、運用データが含まれるようになれば、モデルから再作成することが実用的ではなくなります。その時点で、データベース優先のアプローチに戻ります)。
チュートリアルのこのセクションでは、単純なデータ モデルを作成し、そこからデータベースを生成します。
ソリューション エクスプローラーで、DAL フォルダーを右クリックし、[新しい項目の追加] を選択します。 [新しい項目の追加] ダイアログ ボックスの [インストールされているテンプレート] で [データ] を選択し、次に [ADO.NET Entity Data Model] テンプレートを選びます。 新しいファイルに「AlumniAssociationModel.edmx」という名前を付け、[追加] をクリックします。
これにより、Entity Data Model ウィザードが起動します。 「モデルのコンテンツの選択」手順で、[空のモデル] を選択し、[完了] をクリックします。
Entity Data Model デザイナーが開き、空白のデザイン サーフェスが表示されます。 [ツールボックス] からデザイン サーフェイスに [エンティティ] 項目をドラッグします。
エンティティ名を Entity1
から Alumnus
に変更し、Id
プロパティ名を AlumnusId
に変更して、Name
という名前の新しいスカラー プロパティを追加します。 新しいプロパティを追加するには、Id
列の名前を変更した後に Enter キーを押すか、エンティティを右クリックして [スカラー プロパティの追加] を選択します。 新しいプロパティの既定の型はString
です。この簡単なデモでも問題ありませんが、もちろん [プロパティ] ウィンドウでデータ型などを変更できます。
同じ方法で別のエンティティを作成し、Donation
と名前を付けます。 Id
プロパティを DonationId
に変更し、DateAndAmount
という名前のスカラー プロパティを追加します。
これら 2 つのエンティティ間に関連付けを追加するには、Alumnus
エンティティを右クリックし、[追加] を選択してから [関連付け] を選びます。
[関連付けの追加] ダイアログ ボックスの既定値を自由に設定し (一対多、ナビゲーション プロパティを含む、外部キーを含める)、[OK] をクリックします。
デザイナーによって関連行と外部キー プロパティが追加されます。
これで、データベースを作成する準備ができました。 デザイン サーフェイスを右クリックし、[モデルからデータベースを生成する] を選択します。
これにより、データベース生成ウィザードが起動します (エンティティがマップされていないことを示す警告が表示されても、当面は無視できます)。
「データ接続の選択」の手順で、 [新しい接続] をクリックします。
[接続のプロパティ] ダイアログ ボックスで、ローカルの SQL Server Express インスタンスを選択し、データベースに AlumniAssociation
と名前を付けます。
データベースを作成するかどうかを確認するメッセージが表示されたら、[はい] をクリックします。 「データ接続の選択」手順が再び表示されたら、[次へ] をクリックします。
「概要と設定」手順で、[完了] をクリックします。
データ定義言語 (DDL) コマンドを含む .sql ファイルが作成されますが、コマンドはまだ実行されていません。
SQL Server Management Studio などのツールを使用してスクリプトを実行し、テーブルを作成します。これは、チュートリアル入門シリーズの最初のチュートリアルで School
データベースを作成したときに行った方法と同様です (データベースをダウンロードした場合を除く)。
これで、Web ページ内の AlumniAssociation
データ モデルを、School
モデルを使用する場合と同じ方法で使用できるようになりました。 このデータ モデルを試すには、テーブルにいくつかのデータを追加し、データを表示する Web ページを作成します。
サーバー エクスプローラーを使用して、次の行を Alumnus
テーブルと Donation
テーブルに追加します。
Site.Master マスターページを使用する「Alumni.aspx」 という名前の Web ページを新規作成します。 次のマークアップを Content2
という名前の Content
コントロールに追加します。
<h2>Alumni</h2>
<asp:EntityDataSource ID="AlumniEntityDataSource" runat="server"
ContextTypeName="ContosoUniversity.DAL.AlumniAssociationModelContainer" EnableFlattening="False"
EntitySetName="Alumni">
</asp:EntityDataSource>
<asp:GridView ID="AlumniGridView" runat="server"
DataSourceID="AlumniEntityDataSource" AutoGenerateColumns="False"
OnRowDataBound="AlumniGridView_RowDataBound"
DataKeyNames="AlumnusId">
<Columns>
<asp:BoundField DataField="Name" HeaderText="Name" SortExpression="Name" />
<asp:TemplateField HeaderText="Donations">
<ItemTemplate>
<asp:GridView ID="DonationsGridView" runat="server" AutoGenerateColumns="False">
<Columns>
<asp:BoundField DataField="DateAndAmount" HeaderText="Date and Amount" />
</Columns>
</asp:GridView>
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
このマークアップにより、外側には Alumni の名前を、内側には寄付の日付と金額を表示する、入れ子になった GridView
コントロールが作成されます。
Alumni.aspx.cs を開きます。 データ アクセス層の using
ステートメントと、外側の GridView
コントロールの RowDataBound
イベントに対応するハンドラーを追加します。
using ContosoUniversity.DAL;
// ...
protected void AlumniGridView_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
var alumnus = e.Row.DataItem as Alumnus;
var donationsGridView = (GridView)e.Row.FindControl("DonationsGridView");
donationsGridView.DataSource = alumnus.Donations.ToList();
donationsGridView.DataBind();
}
}
このコードは、現在の行の GridView
エンティティの Donations
ナビゲーション プロパティを使用して、内側にある Alumnus
コントロールのデータをバインドします。
このページを実行します。
(注: このページはダウンロード可能なプロジェクトに含まれていますが、機能させるには、ローカルの SQL Server Express インスタンスにデータベースを作成する必要があります。データベースは、App_Data フォルダーには .mdf ファイルとして含まれていません。)
Entity Framework の Model-First 機能の使用の詳細については、「Entity Framework 4 の Model-First」を参照してください。
POCO サポート
ドメイン駆動型の設計手法を使用する場合は、ビジネス ドメインに関連するデータと動作を表すデータ クラスを設計します。 これらのクラスは、データの格納 (永続化) に使用される特定のテクノロジとは無関係である必要があります。つまり、"永続化非依存" が必須となります。 永続化非依存であれば、単体テスト プロジェクトでテストに最も有用な永続化テクノロジを使用できるため、クラスの単体テストも簡単になります。 以前のバージョンの Entity Framework では、エンティティ クラスで EntityObject
クラスを継承する必要があり、これにより Entity Framework 固有の機能が多数含まれていたため、永続化非依存に対するサポートが制限されていました。
Entity Framework 4 には、EntityObject
クラスから継承されないエンティティ クラスを使用する機能が導入されているため、永続化非依存となります。 一般的に Entity Framework のコンテキストでは、このようなクラスを "Plain Old CLR Object" (POCO) と呼んでいます。 POCO クラスは手動で書き込むことも、Entity Framework によって提供されるテキスト テンプレート変換ツールキット (T4) テンプレートを使用して、既存のデータ モデルに基づいて自動的に生成することもできます。
Entity Framework で POCO を使用する方法の詳細については、次のリソースを参照してください。
- POCO エンティティの使用。 これは、POCO の概要が記載された MSDN ドキュメントです。より詳細な情報を含む他のドキュメントへのリンクも記載されています。
- チュートリアル: Entity Framework 用の POCO テンプレート。Entity Framework 開発チームによるブログ投稿で、POC に関する他のブログ投稿へのリンクが含まれています。
Code-First 開発
Entity Framework 4 の POCO サポートでは、引き続きデータ モデルを作成し、エンティティ クラスをデータ モデルにリンクする必要があります。 Entity Framework の次のリリースには、"Code-First 開発" と呼ばれる機能が含まれる予定です。 この機能を使用すると、データ モデル デザイナーまたはデータ モデル XML ファイルを使用しなくても、独自の POCO クラスで Entity Framework を使用できます (したがって、このオプションは "code-only (コード専用)" とも呼ばれています。"code-first (コード優先)" と "code-only" は、どちらも同じ Entity Framework 機能を参照します)。
開発に Code-First 手法を使用する場合の詳細については、次のリソースを参照してください。
- Entity Framework 4 を使用した Code-First 開発。 これは、Scott Guthrie による、Code-First 開発の紹介に関するブログ記事です。
- Entity Framework 開発チームのブログ - CodeOnly というタグが付いた投稿
- Entity Framework 開発チームのブログ - Code First というタグが付いた投稿
- MVC Music Store のチュートリアル - パート 4: モデルとデータ アクセス
- MVC 3 の概要 - パート 4: Entity Framework の Code-First 開発
さらに、Contoso University アプリケーションと同様のアプリケーションを構築する新しい MVC Code-First チュートリアルが、2011 年春に https://asp.net/entity-framework/tutorials で公開される予定です。
その他の情報
これで、Entity Framework の新機能の概要と、続きとなる Entity Framework チュートリアル シリーズについては完了です。 ここでは説明されていない Entity Framework 4 の新機能の詳細については、次のリソースを参照してください。
- ADO.NET の新機能: Entity Framework バージョン 4 の新機能に関する MSDN トピック。
- Entity Framework 4 のリリースの発表: Entity Framework 開発チームによる、バージョン 4 の新機能に関するブログ投稿。