Share via


Entity Framework 4.0 Database First と ASP.NET 4 Web Formsを使用したはじめに - パート 6

作成者: Tom Dykstra

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) にのみ適用され、一部は両方に適用されます (LastNameFirstName)。

image11

エンティティから継承する エンティティと Student を作成Instructorするように Entity Framework をPerson構成できます。 1 つのデータベース テーブルからエンティティ継承構造を生成するこのパターンは、 階層ごとのテーブル (TPH) 継承と呼ばれます。

コースの場合、データベースでは School 別のパターンが使用されます。 オンライン コースとオンサイト コースは、それぞれテーブルを指す外部キーを持つ個別のテーブルに Course 格納されます。 両方のコースの種類に共通する情報は、テーブルにのみ Course 格納されます。

image12

エンティティとOnsiteCourseエンティティがエンティティから継承されるように OnlineCourse Entity Framework データ モデルをCourse構成できます。 このパターンでは、型ごとに個別のテーブルからエンティティ継承構造を生成します。各個別のテーブルは、すべての型に共通するデータを格納するテーブルを参照し、型 ごとのテーブル (TPT) 継承と呼ばれます。

TPT の継承パターンでは複雑な結合クエリが発生する可能性があるため、TPH 継承パターンは通常、TPT 継承パターンよりも Entity Framework のパフォーマンスが向上します。 このチュートリアルでは、TPH 継承を実装する方法について説明します。 これを行うには、次の手順を実行します。

  • からPerson派生する エンティティ型と Student エンティティ型を作成Instructorします。
  • 派生エンティティに関連するプロパティをエンティティから Person 派生エンティティに移動します。
  • 派生型のプロパティに制約を設定します。
  • エンティティを Person 抽象エンティティにします。
  • 行がその派生型を Person 表すかどうかを判断する方法を指定する条件を使用して、各派生エンティティを Person テーブルにマップします。

講師エンティティと学生エンティティの追加

SchoolModel.edmx ファイルを開き、デザイナーで空き領域を右クリックし、[追加] を選択し、[エンティティ] を選択します

image01

[ エンティティの追加 ] ダイアログ ボックスで、エンティティ Instructor に名前を付け、その [基本型] オプションを に Person設定します。

image02

[OK] をクリックします。 デザイナーは、 Instructor エンティティから派生するエンティティを Person 作成します。 新しいエンティティには、まだプロパティがありません。

image03

プロシージャを繰り返して、 Student から Person派生するエンティティを作成します。

講師のみが採用日を持っているので、そのプロパティをエンティティから Person エンティティに移動する Instructor 必要があります。 エンティティで Person 、 プロパティを HireDate 右クリックし、 [ 切り取り] をクリックします。 次に、エンティティの Instructor[プロパティ] を右クリックし、[貼り付け] をクリックします。

image04

エンティティの雇用日を Instructor null にすることはできません。 プロパティをHireDate右クリックし、[プロパティ] をクリックし、[プロパティ] ウィンドウで にFalse変更Nullableします。

image05

エンティティからエンティティにプロパティを EnrollmentDate 移動するには、 Person この手順を Student 繰り返します。 プロパティについても を にFalseEnrollmentDate設定Nullableしてください。

エンティティに Person 共通 Instructor するプロパティと Student エンティティ (移動していないナビゲーション プロパティを除く) のみが含まれるようになったので、エンティティは継承構造の基本エンティティとしてのみ使用できます。 そのため、独立したエンティティとして扱われないようにする必要があります。 エンティティを Person 右クリックし、[ プロパティ] を選択し、[ プロパティ ] ウィンドウで Abstract プロパティの値を True に変更 します

image06

講師と学生のエンティティを Person テーブルにマッピングする

次に、データベース内の エンティティと Student エンティティを区別Instructorする方法を Entity Framework に指示する必要があります。

エンティティを Instructor 右クリックし、[ テーブル マッピング] を選択します。 [ マッピングの詳細 ] ウィンドウで、[ テーブルまたはビューの追加 ] をクリックし、[ユーザー] を選択 します

image07

[ 条件の追加] をクリックし、[ HireDate] を選択します。

image09

演算子Is に、Value / Property をNot Null に変更します。

image10

列が null でない場合に、このエンティティがテーブルにマップされることを指定して、エンティティのPersonプロシージャStudentsEnrollmentDate繰り返します。 次に、データ モデルを保存して閉じます。

新しいエンティティをクラスとして作成し、デザイナーで使用できるようにするためにプロジェクトをビルドします。

講師エンティティと学生エンティティの使用

学生および講師のデータを操作する Web ページを作成すると、それらをエンティティ セットにPersonデータ連結し、 または EnrollmentDate プロパティでHireDateフィルター処理して、返されるデータを学生または講師に制限しました。 ただし、各データ ソース コントロールをエンティティ セットにPersonバインドするときに、または Instructor エンティティ型のみをStudent選択するように指定できるようになりました。 Entity Framework は、エンティティ セット内の学生と講師を区別する方法を Person 認識しているため、手動で入力したプロパティ設定を削除 Where してこれを行うことができます。

Visual Studio Designerでは、次の例に示すように、ウィザードの [EntityTypeFilter] ドロップダウン ボックスでコントロールが選択するエンティティのConfigure Data Source種類EntityDataSourceを指定できます。

image13

次の例に示すように、[ プロパティ ] ウィンドウでは、不要になった句値を削除 Where できます。

image14

ただし、 属性を使用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 + '%'" >

ページを実行して、以前と同じように動作することを確認します。

image15

前のチュートリアルで作成した次のページを更新して、エンティティではなく新しい 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>
    

    image16

  • 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>
    

    image17

  • Instructors.aspxInstructorsCourses.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>
    

    image18

    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>
    

    image19

これらの変更の結果、Contoso University アプリケーションの保守性がいくつかの点で向上しました。 選択ロジックと検証ロジックを UI レイヤー (.aspx マークアップ) から移動し、データ アクセス レイヤーの不可欠な部分にしました。 これにより、アプリケーション コードを、将来データベース スキーマまたはデータ モデルに加える可能性のある変更から分離するのに役立ちます。 たとえば、学生が教師の補助として採用され、したがって採用日が得られる可能性があると判断できます。 その後、新しいプロパティを追加して、学生と講師を区別し、データ モデルを更新できます。 Web アプリケーションのコードは、学生の採用日を表示する場所を除き、変更する必要はありません。 エンティティと Student エンティティを追加Instructorするもう 1 つの利点は、実際に学生や講師であったオブジェクトをPerson参照する場合よりも、コードを容易に理解できるという点です。

Entity Framework で継承パターンを実装する方法の 1 つを見てきました。 次のチュートリアルでは、Entity Framework がデータベースにアクセスする方法をより細かく制御するためにストアド プロシージャを使用する方法について説明します。