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 エンティティには含まれていません。

Image01

このアプローチの理由は、厳密に言えば外部キーが物理的な実装の一部であり、概念的なデータ モデルではないからです。 ただし、実際には、外部キーに直接アクセスできればコード内のエンティティを簡単に操作できます。

データ モデルで外部キーを使用してコードを簡略化する方法の例では、外部キーを使用せずに 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 ページを実行して、データの "前" の画像を取得します。

Image02

UpdateCredits.aspx を実行し、乗数に「10」と入力してから [実行] をクリックします。

Image03

Courses.aspx ページをもう一度実行して、変更されたデータを確認します。

Image04

(クレジットの数を元の値に戻す場合は、UpdateCredits.aspx.csCredits * {0}Credits / {0} に変更し、除数に「10」と入力してからページを再実行します。)

コードで定義するクエリの実行の詳細については、「方法: データ ソースに対してコマンドを直接実行する」を参照してください。

Model-First 開発

これらのチュートリアルでは、まずデータベースを作成し、次にデータベースの構造に基づいてデータ モデルを生成しました。 Entity Framework 4 では、代わりにデータ モデルから開始し、次にデータ モデルの構造に基づいてデータベースを生成できます。 データベースがまだ存在しないアプリケーションを作成する場合でも、モデル優先のアプローチによって、物理的な実装の詳細を気にすることなく、アプリケーションにとって概念的に意味のあるエンティティとリレーションシップを作成できます (ただし、これは開発の初期段階でのみ当てはまります。最終的にデータベースが作成され、運用データが含まれるようになれば、モデルから再作成することが実用的ではなくなります。その時点で、データベース優先のアプローチに戻ります)。

チュートリアルのこのセクションでは、単純なデータ モデルを作成し、そこからデータベースを生成します。

ソリューション エクスプローラーで、DAL フォルダーを右クリックし、[新しい項目の追加] を選択します。 [新しい項目の追加] ダイアログ ボックスの [インストールされているテンプレート][データ] を選択し、次に [ADO.NET Entity Data Model] テンプレートを選びます。 新しいファイルに「AlumniAssociationModel.edmx」という名前を付け、[追加] をクリックします。

Image06

これにより、Entity Data Model ウィザードが起動します。 「モデルのコンテンツの選択」手順で、[空のモデル] を選択し、[完了] をクリックします。

Image07

Entity Data Model デザイナーが開き、空白のデザイン サーフェスが表示されます。 [ツールボックス] からデザイン サーフェイスに [エンティティ] 項目をドラッグします。

Image08

エンティティ名を Entity1 から Alumnus に変更し、Id プロパティ名を AlumnusId に変更して、Name という名前の新しいスカラー プロパティを追加します。 新しいプロパティを追加するには、Id 列の名前を変更した後に Enter キーを押すか、エンティティを右クリックして [スカラー プロパティの追加] を選択します。 新しいプロパティの既定の型はString です。この簡単なデモでも問題ありませんが、もちろん [プロパティ] ウィンドウでデータ型などを変更できます。

同じ方法で別のエンティティを作成し、Donation と名前を付けます。 Id プロパティを DonationId に変更し、DateAndAmount という名前のスカラー プロパティを追加します。

Image09

これら 2 つのエンティティ間に関連付けを追加するには、Alumnus エンティティを右クリックし、[追加] を選択してから [関連付け] を選びます。

Image10

[関連付けの追加] ダイアログ ボックスの既定値を自由に設定し (一対多、ナビゲーション プロパティを含む、外部キーを含める)、[OK] をクリックします。

Image11

デザイナーによって関連行と外部キー プロパティが追加されます。

Image12

これで、データベースを作成する準備ができました。 デザイン サーフェイスを右クリックし、[モデルからデータベースを生成する] を選択します。

Image13

これにより、データベース生成ウィザードが起動します (エンティティがマップされていないことを示す警告が表示されても、当面は無視できます)。

データ接続の選択」の手順で、 [新しい接続] をクリックします。

Image14

[接続のプロパティ] ダイアログ ボックスで、ローカルの SQL Server Express インスタンスを選択し、データベースに AlumniAssociation と名前を付けます。

Image15

データベースを作成するかどうかを確認するメッセージが表示されたら、[はい] をクリックします。 「データ接続の選択」手順が再び表示されたら、[次へ] をクリックします。

概要と設定」手順で、[完了] をクリックします。

Image18

データ定義言語 (DDL) コマンドを含む .sql ファイルが作成されますが、コマンドはまだ実行されていません。

Image20

SQL Server Management Studio などのツールを使用してスクリプトを実行し、テーブルを作成します。これは、チュートリアル入門シリーズの最初のチュートリアルSchool データベースを作成したときに行った方法と同様です (データベースをダウンロードした場合を除く)。

これで、Web ページ内の AlumniAssociation データ モデルを、School モデルを使用する場合と同じ方法で使用できるようになりました。 このデータ モデルを試すには、テーブルにいくつかのデータを追加し、データを表示する Web ページを作成します。

サーバー エクスプローラーを使用して、次の行を Alumnus テーブルと Donation テーブルに追加します。

Image21

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 コントロールのデータをバインドします。

このページを実行します。

Image22

(注: このページはダウンロード可能なプロジェクトに含まれていますが、機能させるには、ローカルの 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 を使用する方法の詳細については、次のリソースを参照してください。

Code-First 開発

Entity Framework 4 の POCO サポートでは、引き続きデータ モデルを作成し、エンティティ クラスをデータ モデルにリンクする必要があります。 Entity Framework の次のリリースには、"Code-First 開発" と呼ばれる機能が含まれる予定です。 この機能を使用すると、データ モデル デザイナーまたはデータ モデル XML ファイルを使用しなくても、独自の POCO クラスで Entity Framework を使用できます (したがって、このオプションは "code-only (コード専用)" とも呼ばれています。"code-first (コード優先)" と "code-only" は、どちらも同じ Entity Framework 機能を参照します)。

開発に Code-First 手法を使用する場合の詳細については、次のリソースを参照してください。

さらに、Contoso University アプリケーションと同様のアプリケーションを構築する新しい MVC Code-First チュートリアルが、2011 年春に https://asp.net/entity-framework/tutorials で公開される予定です。

その他の情報

これで、Entity Framework の新機能の概要と、続きとなる Entity Framework チュートリアル シリーズについては完了です。 ここでは説明されていない Entity Framework 4 の新機能の詳細については、次のリソースを参照してください。