チュートリアル: Table-Per-Type 継承のマッピング (Entity Data Model ツール)

このトピックでは、概念モデルを変更することによって Table-Per-Type 継承を実装する方法を説明します。 Table-Per-Type 継承は、データベース内の別個のテーブルを使用して、非継承プロパティと継承階層のそれぞれの型のキー プロパティのデータを維持します。

このチュートリアルでは、CourseManager アプリケーションで使用する概念モデルを変更することによって、Table-Per-Type 継承を実装します (詳細は、このトピックの「前提条件」を参照してください)。

CourseManager アプリケーションでは、CourseOnlineCourse、および OnsiteCourse エンティティ型は同じ名前のテーブルにマップされます。 OnlineCourse および OnsiteCourse エンティティ型は、2 つのコース型に固有の情報を格納し、共通のキーを共有しているため、Course エンティティ型から継承するよう変更できます。 以下の手順は、この場合の Table-Per-Type 継承を実装する方法をまとめたものです (このトピックの後半では、これらの手順について詳しく説明します)。

  1. OnlineCourse エンティティ型と Course エンティティ型の間のアソシエーションを削除します。 OnsiteCourse エンティティ型と Course エンティティ型の間のアソシエーションを削除します。 これらのアソシエーションは、継承階層の実装によって置き換えられます。

  2. OnlineCourse および OnsiteCourse エンティティ型から CourseID キー プロパティを削除します。 このプロパティは、Course エンティティ型から継承されます。

  3. Course エンティティ型を OnlineCourse および OnsiteCourse エンティティ型の基本データ型として設定します。

  4. Course エンティティ型を抽象型にします。

  5. OnlineCourse および OnsiteCourse エンティティ型の継承された CourseID プロパティを適切な列にマップします。

前提条件

このチュートリアルを完了するには、最初に CourseManager アプリケーションを構築する必要があります。 詳細と手順については、「Entity Framework クイック スタート」を参照してください。 CourseManager アプリケーションで使用する概念モデルを変更することにより、Table-Per-Type 継承を実装します。 選択した部門のオンライン コースとオンサイト コースを別々に表示するには、アプリケーションの機能を拡張します。

Cc716702.note(ja-jp,VS.100).gif注 :
このドキュメントのチュートリアルのトピックの多くは CourseManager アプリケーションを開始点としているため、元の CourseManager コードを編集するのではなく、このチュートリアル用に CourseManager アプリケーションのコピーを使用することをお勧めします。

このチュートリアルでは、Visual Studio、.NET Framework、および Visual C# または Visual Basic のプログラミングの基本的なスキルがある読者を想定しています。

Table-Per-Type 継承の実装

この手順では、Table-Per-Type 継承を実装することによって SchoolModel を変更します。 以下の手順のビデオ プレゼンテーションを視聴するには、「操作方法」を参照してください。

Table-Per-Type 継承を実装するには

  1. Visual Studio で CourseManager ソリューションを開きます。

  2. ソリューション エクスプローラーで、School.edmx ファイルをダブルクリックします。

    Entity Data Model デザイナー (エンティティ デザイナー) で School.edmx ファイルが開きます。

  3. OnlineCourse エンティティ型を右クリックし、[プロパティ] をクリックします。

  4. [プロパティ] ウィンドウで、[基本データ型] プロパティを Course に設定します。

  5. OnsiteCourse エンティティ型について、手順 3. と 4. を繰り返します。

  6. OnlineCourse エンティティ型と Course エンティティ型の間のアソシエーション (線) を右クリックします。 [削除] をクリックします。

  7. OnsiteCourse エンティティ型と Course エンティティ型の間のアソシエーションを右クリックします。 [削除] をクリックします。

  8. OnlineCourse エンティティ型の CourseID プロパティを右クリックし、[削除] をクリックします。

  9. OnsiteCourse エンティティ型の CourseID プロパティを右クリックし、[削除] をクリックします。

  10. Course エンティティ型を選択します。 [プロパティ] ウィンドウで、[抽象] プロパティを true に設定します。

    エンティティ型を抽象型として定義するとその型の既存の関数マッピングがすべて削除されることを通知するメッセージ ボックスが表示されます。 [OK] をクリックします。

    Cc716702.note(ja-jp,VS.100).gif注 :
    Course エンティティ型が抽象型に変更されたため、元の CourseManager アプリケーションの更新機能は動作しなくなります。

  11. OnlineCourse エンティティ型を右クリックし、[テーブル マッピング] をクリックします。

    [マッピングの詳細] ウィンドウが表示されます。

  12. CourseID 列に対応する [値/プロパティ] フィールドをクリックします。

    [値/プロパティ] フィールドは、対応する列にマップできるプロパティを示すドロップダウン リストになります。

  13. ドロップダウン リストから [CourseID] を選択します。

  14. OnsiteCourse エンティティ型について、手順 11. と 13. を繰り返します。

これで、Table-Per-Type 継承が実装されました。

ユーザー インターフェイスの構築

次に、CourseDiscrimForm フォームを読み込んで表示するボタンを CourseViewer フォームに追加します。 さらに、OnsiteCourses および OnlineCourses を表示するための 2 つの DataGridView コントロールを追加します。 最後に、DataGridViewBindingSource コントロールにバインドします。 オブジェクトをコントロールにバインドする方法の詳細については、「Binding Objects to Controls (Entity Framework)」を参照してください。

ユーザー インターフェイスを構築するには

  1. ソリューション エクスプローラーで CourseManager プロジェクトを右クリックし、[追加] をポイントして、[新しい項目] をクリックします。

    [新しい項目の追加] ダイアログ ボックスが表示されます。

  2. [Windows フォーム] を選択し、[追加] をクリックします。

    新しいフォームがプロジェクトに追加され、フォーム デザイナーで開かれます。

  3. [プロパティ] ウィンドウで、フォーム名を CourseDiscriminator に設定します。

    新しいフォームがプロジェクトに追加され、フォーム デザイナーで開かれます。 フォーム名が CourseDiscriminator に、テキストが CourseDiscriminator に設定されます。

  4. ComboBox コントロールをツールボックスからフォームにドラッグし、[プロパティ] ウィンドウで名前を departmentList に設定します。

  5. DataGridView コントロールをツールボックスからフォームにドラッグし、名前を onsiteGridView に設定します。

  6. 別の DataGridView コントロールをツールボックスからフォームにドラッグし、名前を onlineGridView に設定します。

  7. ソリューション エクスプローラーで、CourseViewer.cs または CourseViewer.vb をダブルクリックします。

    CourseViewer フォームのデザイン ビューが表示されます。

  8. Button コントロールをツールボックスから CourseViewer フォームにドラッグします。

  9. [プロパティ] ウィンドウで、Button の名前を viewDiscriminator に設定し、ボタンのテキストを Online vs. Onsite に設定します。

  10. viewDiscriminator Button をダブルクリックします。

    フォームの分離コード ファイルが開きます。

  11. viewDiscriminator_click イベント ハンドラーに次のコードを追加します。

    Dim courseDiscrim As New CourseDiscriminator
    courseDiscrim.Visible = True
    
    CourseDiscriminator courseDiscrim = new CourseDiscriminator();
    courseDiscrim.Visible = true;
    

このフォームのユーザー インターフェイスが完成しました。

概念モデルに対するクエリ

この手順では、概念モデルに対してクエリを実行し、結果を Windows フォーム コントロールにバインドします。

概念モデルに対してクエリを実行するには

  1. フォーム デザイナーで CourseDiscriminator フォームを開きます。

  2. BindingSource コントロールをツールボックスからフォームにドラッグします。

  3. [プロパティ] ウィンドウで、BindingSource の名前を onsiteBindingSource に設定します。

  4. [プロパティ] ウィンドウで、DataSource プロパティの横にあるフィールドをクリックします。

    フィールドは、使用可能なデータ ソースを示すドロップダウン リストになります。

  5. [プロジェクト データ ソースの追加] をクリックします。

    データ ソース構成ウィザード[データ ソースの種類を選択] ウィンドウが開きます。

  6. [アプリケーションがデータを取得する場所]ボックスから、[オブジェクト] を選択します。

  7. [次へ] をクリックします。

    [バインド先のオブジェクトを選択します。] ウィンドウが開きます。 使用可能なリソースのツリーの最上位ノードが表示されます。

  8. CourseManager ノードを展開して、CourseManager 子ノードを展開します。

  9. OnsiteCourse を選択し、[完了] をクリックします。

  10. 手順 2. ~ 9. を繰り返します。ただし、BindingSource コントロールの名前は OnlineBindingSource とし、OnlineCourse オブジェクトにバインドします。

  11. OnsiteGridView コントロールを右クリックし、[プロパティ] をクリックします。

  12. [プロパティ] ウィンドウで、DataSource プロパティの横にあるフィールドをクリックします。

    フィールドは、使用可能なデータ ソースを示すドロップダウン リストになります。

  13. OnsiteBindingSource を選択します。

  14. OnlineGridView について、手順 11. ~ 13. を繰り返します。ただし、DataSouce プロパティは OnlineBindingSource に設定します。

    Cc716702.note(ja-jp,VS.100).gif注 :
    OfType メソッドは、DataGridView コントロールが実行時に列を生成できない列挙を返します。この例で目的の情報を表示するには、バインド対象のクラスに基づいて、デザイン時に DataGridView コントロール用のデータ ソースを BindingSource コントロールを使用して設定します。

  15. CourseDiscriminator フォームをダブルクリックします。

    CourseDiscriminator フォームの分離コード ファイルが開きます。

  16. 次の using (C#) ステートメントまたは Imports (Visual Basic) ステートメントを追加して、School データベースから作成されたモデルとエンティティの名前空間を参照します。

    Imports System.Data.Objects
    Imports System.Data.Objects.DataClasses
    
    using System.Data.Objects;
    using System.Data.Objects.DataClasses;
    
  17. データ コンテキストを表すプロパティを CourseDiscriminator クラスに追加します。

    ' Create an ObjectContext instance based on SchoolEntity.
    Private schoolContext As SchoolEntities
    
    // Create an ObjectContext instance based on SchoolEntity.
    private SchoolEntities schoolContext;
    
  18. CourseDiscriminator_Load イベント ハンドラーで、オブジェクト コンテキストを初期化して、Department 情報を返すクエリに departmentList コントロールをバインドするコードを追加します。

    ' Initialize the ObjectContext.
    schoolContext = New SchoolEntities()
    
    ' Define a query that returns all Department objects and 
    ' related Course objects, ordered by name.
    Dim departmentQuery As ObjectQuery(Of Department) = _
        schoolContext.Departments.Include("Courses").OrderBy("it.Name")
    
    ' Bind the ComboBox control to the query, which is
    ' executed during data binding.
    departmentList.DisplayMember = "Name"
    departmentList.DataSource = departmentQuery. _
        Execute(MergeOption.OverwriteChanges)
    
    // Initialize the ObjectContext.
    schoolContext = new SchoolEntities();
    
    // Define a query that returns all Department objects  
    // and related Course objects, ordered by name.
    ObjectQuery<Department> departmentQuery = 
        schoolContext.Departments.Include("Courses").
        OrderBy("it.Name");
    
    // Bind the ComboBox control to the query.
    this.departmentList.DisplayMember = "Name";
    this.departmentList.DataSource = departmentQuery.
        Execute(MergeOption.OverwriteChanges);
    
  19. CourseDiscriminator フォームのデザイナー ビューに戻り、departmentList ComboBox コントロールをダブルクリックします。

    分離コード ファイルが開きます。 departmentList_SelectedIndexChanged イベント ハンドラーがコードに追加されました。

  20. departmentList_SelectedIndexChanged イベント ハンドラーに次のコードを追加して、BindingSource コントロールのデータ ソースを更新します。

    ' Get the selected department object.
    Dim department As Department = CType(Me.departmentList. _
            SelectedItem, Department)
    
    ' Update the data sources for the BindingSource controls.
    onsiteBindingSource.DataSource = department.Courses _
        .OfType(Of OnsiteCourse)()
    onlineBindingSource.DataSource = department.Courses _
        .OfType(Of OnlineCourse)()
    
    // Get the selected department object.
    Department department = (Department)this.departmentList
        .SelectedItem;
    
    // Update the data sources for the BindingSource controls.
    onsiteBindingSource.DataSource = department.Courses.
        OfType<OnsiteCourse>();
    onlineBindingSource.DataSource = department.Courses.
        OfType<OnlineCourse>();
    

アプリケーションが完成しました。 Ctrl キーを押しながら F5 キーを押してアプリケーションを実行します。 [Onsite vs. Online] ボタンをクリックして、CourseDiscriminator フォームを読み込みます。 選択した部門用の OnsiteCoursesOnlineCoursesDataGridView コントロールに表示されます。

コード リスト

このセクションでは、CourseDiscriminator フォームの分離コード ファイルの最終バージョンを示します。

Imports System.Data.Objects
Imports System.Data.Objects.DataClasses
Public Class CourseDiscriminator

    ' Create an ObjectContext instance based on SchoolEntity.
    Private schoolContext As SchoolEntities

    Private Sub CourseDiscriminator_Load(ByVal sender As System. _
        Object, ByVal e As System.EventArgs) Handles MyBase.Load
        ' Initialize the ObjectContext.
        schoolContext = New SchoolEntities()

        ' Define a query that returns all Department objects and 
        ' related Course objects, ordered by name.
        Dim departmentQuery As ObjectQuery(Of Department) = _
            schoolContext.Departments.Include("Courses").OrderBy("it.Name")

        ' Bind the ComboBox control to the query, which is
        ' executed during data binding.
        departmentList.DisplayMember = "Name"
        departmentList.DataSource = departmentQuery. _
            Execute(MergeOption.OverwriteChanges)
    End Sub

    Private Sub departmentList_SelectedIndexChanged(ByVal sender As  _
        System.Object, ByVal e As System.EventArgs) Handles _
        departmentList.SelectedIndexChanged
        ' Get the selected department object.
        Dim department As Department = CType(Me.departmentList. _
                SelectedItem, Department)

        ' Update the data sources for the BindingSource controls.
        onsiteBindingSource.DataSource = department.Courses _
            .OfType(Of OnsiteCourse)()
        onlineBindingSource.DataSource = department.Courses _
            .OfType(Of OnlineCourse)()
    End Sub
End Class
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Data.Objects;
using System.Data.Objects.DataClasses;

namespace CourseManager
{
    public partial class CourseDiscriminator : Form
    {
        // Create an ObjectContext instance based on SchoolEntity.
        private SchoolEntities schoolContext;

        public CourseDiscriminator()
        {
            InitializeComponent();
        }

        private void CourseDiscriminator_Load(object sender,
            EventArgs e)
        {
            // Initialize the ObjectContext.
            schoolContext = new SchoolEntities();

            // Define a query that returns all Department objects  
            // and related Course objects, ordered by name.
            ObjectQuery<Department> departmentQuery = 
                schoolContext.Departments.Include("Courses").
                OrderBy("it.Name");

            // Bind the ComboBox control to the query.
            this.departmentList.DisplayMember = "Name";
            this.departmentList.DataSource = departmentQuery.
                Execute(MergeOption.OverwriteChanges);
        }

        private void departmentList_SelectedIndexChanged(object sender,
            EventArgs e)
        {
            // Get the selected department object.
            Department department = (Department)this.departmentList
                .SelectedItem;

            // Update the data sources for the BindingSource controls.
            onsiteBindingSource.DataSource = department.Courses.
                OfType<OnsiteCourse>();
            onlineBindingSource.DataSource = department.Courses.
                OfType<OnlineCourse>();
        }
    }
}

次の手順

概念モデルに Table-Per-Type 継承を正常に実装できました。 Table-Per-Type 継承を持つ概念モデルを定義する方法の詳細については、「How to: Define a Model with Table-per-Type Inheritance」を参照してください。 Entity Framework を使用するアプリケーションを構築する方法の詳細については、「ADO.NET Entity Framework」を参照してください。

参照

その他のリソース

Entity Data Model ツールのシナリオ
Entity Data Model ツールのタスク