Entity Framework 4.0 Database First と ASP.NET 4 Web Formsを使用したはじめに - パート 6
Contoso University サンプル Web アプリケーションは、Entity Framework 4.0 と Visual Studio 2010 を使用して ASP.NET Web Forms アプリケーションを作成する方法を示しています。 チュートリアル シリーズの詳細については、シリーズの最初のチュートリアルを参照してください
Table-Per-Hierarchy 継承の実装
前のチュートリアルでは、リレーションシップを追加および削除し、既存のエンティティにリレーションシップを持つ新しいエンティティを追加することで、関連データを操作しました。 このチュートリアルでは、データ モデルで継承を実装する方法を示します。
オブジェクト指向プログラミングでは、継承を使用して、関連するクラスを簡単に操作できます。 たとえば、基底クラスから派生する クラスと Student
クラスをPerson
作成Instructor
できます。 Entity Framework 内のエンティティ間で同じ種類の継承構造を作成できます。
チュートリアルのこの部分では、新しい Web ページは作成しません。 代わりに、派生エンティティをデータ モデルに追加し、新しいエンティティを使用するように既存のページを変更します。
階層ごとのテーブルと型ごとのテーブルの継承
データベースは、関連オブジェクトに関する情報を 1 つのテーブルまたは複数のテーブルに格納できます。 たとえば、データベースの School
テーブルには、 Person
学生と講師の両方に関する情報が 1 つのテーブルに含まれています。 一部の列は講師 (HireDate
) にのみ適用され、一部は学生 (EnrollmentDate
) にのみ適用され、一部は両方に適用されます (LastName
、 FirstName
)。
エンティティから継承する エンティティと Student
を作成Instructor
するように Entity Framework をPerson
構成できます。 1 つのデータベース テーブルからエンティティ継承構造を生成するこのパターンは、 階層ごとのテーブル (TPH) 継承と呼ばれます。
コースの場合、データベースでは School
別のパターンが使用されます。 オンライン コースとオンサイト コースは、それぞれテーブルを指す外部キーを持つ個別のテーブルに Course
格納されます。 両方のコースの種類に共通する情報は、テーブルにのみ Course
格納されます。
エンティティとOnsiteCourse
エンティティがエンティティから継承されるように OnlineCourse
Entity Framework データ モデルをCourse
構成できます。 このパターンでは、型ごとに個別のテーブルからエンティティ継承構造を生成します。各個別のテーブルは、すべての型に共通するデータを格納するテーブルを参照し、型 ごとのテーブル (TPT) 継承と呼ばれます。
TPT の継承パターンでは複雑な結合クエリが発生する可能性があるため、TPH 継承パターンは通常、TPT 継承パターンよりも Entity Framework のパフォーマンスが向上します。 このチュートリアルでは、TPH 継承を実装する方法について説明します。 これを行うには、次の手順を実行します。
- から
Person
派生する エンティティ型とStudent
エンティティ型を作成Instructor
します。 - 派生エンティティに関連するプロパティをエンティティから
Person
派生エンティティに移動します。 - 派生型のプロパティに制約を設定します。
- エンティティを
Person
抽象エンティティにします。 - 行がその派生型を
Person
表すかどうかを判断する方法を指定する条件を使用して、各派生エンティティをPerson
テーブルにマップします。
講師エンティティと学生エンティティの追加
SchoolModel.edmx ファイルを開き、デザイナーで空き領域を右クリックし、[追加] を選択し、[エンティティ] を選択します。
[ エンティティの追加 ] ダイアログ ボックスで、エンティティ Instructor
に名前を付け、その [基本型] オプションを に Person
設定します。
[OK] をクリックします。 デザイナーは、 Instructor
エンティティから派生するエンティティを Person
作成します。 新しいエンティティには、まだプロパティがありません。
プロシージャを繰り返して、 Student
から Person
派生するエンティティを作成します。
講師のみが採用日を持っているので、そのプロパティをエンティティから Person
エンティティに移動する Instructor
必要があります。 エンティティで Person
、 プロパティを HireDate
右クリックし、 [ 切り取り] をクリックします。 次に、エンティティの Instructor
[プロパティ] を右クリックし、[貼り付け] をクリックします。
エンティティの雇用日を Instructor
null にすることはできません。 プロパティをHireDate
右クリックし、[プロパティ] をクリックし、[プロパティ] ウィンドウで にFalse
変更Nullable
します。
エンティティからエンティティにプロパティを EnrollmentDate
移動するには、 Person
この手順を Student
繰り返します。 プロパティについても を にFalse
EnrollmentDate
設定Nullable
してください。
エンティティに Person
共通 Instructor
するプロパティと Student
エンティティ (移動していないナビゲーション プロパティを除く) のみが含まれるようになったので、エンティティは継承構造の基本エンティティとしてのみ使用できます。 そのため、独立したエンティティとして扱われないようにする必要があります。 エンティティを Person
右クリックし、[ プロパティ] を選択し、[ プロパティ ] ウィンドウで Abstract プロパティの値を True に変更 します。
講師と学生のエンティティを Person テーブルにマッピングする
次に、データベース内の エンティティと Student
エンティティを区別Instructor
する方法を Entity Framework に指示する必要があります。
エンティティを Instructor
右クリックし、[ テーブル マッピング] を選択します。 [ マッピングの詳細 ] ウィンドウで、[ テーブルまたはビューの追加 ] をクリックし、[ユーザー] を選択 します。
[ 条件の追加] をクリックし、[ HireDate] を選択します。
演算子を Is に、Value / Property をNot Null に変更します。
列が null でない場合に、このエンティティがテーブルにマップされることを指定して、エンティティのPerson
プロシージャStudents
をEnrollmentDate
繰り返します。 次に、データ モデルを保存して閉じます。
新しいエンティティをクラスとして作成し、デザイナーで使用できるようにするためにプロジェクトをビルドします。
講師エンティティと学生エンティティの使用
学生および講師のデータを操作する Web ページを作成すると、それらをエンティティ セットにPerson
データ連結し、 または EnrollmentDate
プロパティでHireDate
フィルター処理して、返されるデータを学生または講師に制限しました。 ただし、各データ ソース コントロールをエンティティ セットにPerson
バインドするときに、または Instructor
エンティティ型のみをStudent
選択するように指定できるようになりました。 Entity Framework は、エンティティ セット内の学生と講師を区別する方法を Person
認識しているため、手動で入力したプロパティ設定を削除 Where
してこれを行うことができます。
Visual Studio Designerでは、次の例に示すように、ウィザードの [EntityTypeFilter] ドロップダウン ボックスでコントロールが選択するエンティティのConfigure Data Source
種類EntityDataSource
を指定できます。
次の例に示すように、[ プロパティ ] ウィンドウでは、不要になった句値を削除 Where
できます。
ただし、 属性を使用ContextTypeName
するようにコントロールのマークアップEntityDataSource
を変更したため、既に作成したコントロールに対してEntityDataSource
データ ソースの構成ウィザードを実行することはできません。 したがって、代わりにマークアップを変更することで、必要な変更を行います。
Students.aspx ページを開きます。 コントロールで、 StudentsEntityDataSource
属性を Where
削除し、 属性を EntityTypeFilter="Student"
追加します。 マークアップは次の例のようになります。
<asp:EntityDataSource ID="StudentsEntityDataSource" runat="server"
ContextTypeName="ContosoUniversity.DAL.SchoolEntities" EnableFlattening="False"
EntitySetName="People" EntityTypeFilter="Student"
Include="StudentGrades"
EnableDelete="True" EnableUpdate="True"
OrderBy="it.LastName" >
</asp:EntityDataSource>
属性を EntityTypeFilter
設定すると、コントロールは EntityDataSource
指定されたエンティティ型のみを選択します。 エンティティ型と Instructor
エンティティ型の両方Student
を取得する場合は、この属性を設定しません。 (読み取り専用データ アクセスに コントロールを使用している場合にのみ、1 つの EntityDataSource
コントロールで複数のエンティティ型を取得するオプションがあります。コントロールを EntityDataSource
使用してエンティティを挿入、更新、または削除し、バインド先のエンティティ セットに複数の型を含めることができる場合は、1 つのエンティティ型のみを操作でき、この属性を設定する必要があります)。
プロパティを完全にSearchEntityDataSource
削除するのではなく、エンティティを選択Student
する属性のWhere
一部のみを削除する点を除き、コントロールのプロシージャを繰り返します。 コントロールの開始タグは、次の例のようになります。
<asp:EntityDataSource ID="SearchEntityDataSource" runat="server"
ContextTypeName="ContosoUniversity.DAL.SchoolEntities" EnableFlattening="False"
EntitySetName="People" EntityTypeFilter="Student"
Where="it.FirstMidName Like '%' + @StudentName + '%' or it.LastName Like '%' + @StudentName + '%'" >
ページを実行して、以前と同じように動作することを確認します。
前のチュートリアルで作成した次のページを更新して、エンティティではなく新しい Student
エンティティと Instructor
エンティティを使用するようにし、それらを実行して、以前と同じように動作することを確認 Person
します。
StudentsAdd.aspx で、 を コントロールに
StudentsEntityDataSource
追加EntityTypeFilter="Student"
します。 マークアップは次の例のようになります。<asp:EntityDataSource ID="StudentsEntityDataSource" runat="server" ContextTypeName="ContosoUniversity.DAL.SchoolEntities" EnableFlattening="False" EntitySetName="People" EntityTypeFilter="Student" EnableInsert="True" </asp:EntityDataSource>
About.aspx で、 を コントロールに
StudentStatisticsEntityDataSource
追加EntityTypeFilter="Student"
し、 を削除しますWhere="it.EnrollmentDate is not null"
。 マークアップは次の例のようになります。<asp:EntityDataSource ID="StudentStatisticsEntityDataSource" runat="server" ContextTypeName="ContosoUniversity.DAL.SchoolEntities" EnableFlattening="False" EntitySetName="People" EntityTypeFilter="Student" Select="it.EnrollmentDate, Count(it.EnrollmentDate) AS NumberOfStudents" OrderBy="it.EnrollmentDate" GroupBy="it.EnrollmentDate" > </asp:EntityDataSource>
Instructors.aspx と InstructorsCourses.aspx で、 を コントロールに追加
EntityTypeFilter="Instructor"
し、 をInstructorsEntityDataSource
削除しますWhere="it.HireDate is not null"
。 Instructors.aspx のマークアップは、次の例のようになります。<asp:EntityDataSource ID="InstructorsEntityDataSource" runat="server" ContextTypeName="ContosoUniversity.DAL.SchoolEntities" EnableFlattening="false" EntitySetName="People" EntityTypeFilter="Instructor" Include="OfficeAssignment" EnableUpdate="True"> </asp:EntityDataSource>
InstructorsCourses.aspx のマークアップは、次の例のようになります。
<asp:EntityDataSource ID="InstructorsEntityDataSource" runat="server" ContextTypeName="ContosoUniversity.DAL.SchoolEntities" EnableFlattening="False" EntitySetName="People" EntityTypeFilter="Instructor" Select="it.LastName + ',' + it.FirstMidName AS Name, it.PersonID"> </asp:EntityDataSource>
これらの変更の結果、Contoso University アプリケーションの保守性がいくつかの点で向上しました。 選択ロジックと検証ロジックを UI レイヤー (.aspx マークアップ) から移動し、データ アクセス レイヤーの不可欠な部分にしました。 これにより、アプリケーション コードを、将来データベース スキーマまたはデータ モデルに加える可能性のある変更から分離するのに役立ちます。 たとえば、学生が教師の補助として採用され、したがって採用日が得られる可能性があると判断できます。 その後、新しいプロパティを追加して、学生と講師を区別し、データ モデルを更新できます。 Web アプリケーションのコードは、学生の採用日を表示する場所を除き、変更する必要はありません。 エンティティと Student
エンティティを追加Instructor
するもう 1 つの利点は、実際に学生や講師であったオブジェクトをPerson
参照する場合よりも、コードを容易に理解できるという点です。
Entity Framework で継承パターンを実装する方法の 1 つを見てきました。 次のチュートリアルでは、Entity Framework がデータベースにアクセスする方法をより細かく制御するためにストアド プロシージャを使用する方法について説明します。
フィードバック
https://aka.ms/ContentUserFeedback」を参照してください。
以下は間もなく提供いたします。2024 年を通じて、コンテンツのフィードバック メカニズムとして GitHub の issue を段階的に廃止し、新しいフィードバック システムに置き換えます。 詳細については、「フィードバックの送信と表示