逐步解說:對應每個階層的資料表繼承

本主題示範如何在 Entity Data Model (EDM) 中更改概念模型以實作每個階層的資料表繼承。每個階層的資料表繼承都會使用一個資料庫資料表,以維護繼承階層架構 (Inheritance Hierarchy) 中所有實體類型的資料。如需以 EDM 實作階層架構的詳細資訊,請參閱繼承 (EDM)

在本逐步解說中,您將修改 CourseManager 應用程式內使用的 EDM,藉以實作每個階層的資料表繼承 (如需詳細資訊,請參閱本主題稍後的<必要條件>章節)。

在 CourseManager EDM 中,Person 實體類型有兩個屬性 HireDateEnrollmentDate,它們可屬於繼承自 Person 的新實體類型 (分別為 InstructorStudent)。下列步驟概述如何在此案例中實作每個階層的資料表繼承。本逐步解說的程序有提供更詳細的資訊。

  1. 建立兩個新實體類型:InstructorStudent

  2. 將每個新實體類型的基底類型設為 Person

  3. HireDate 屬性從 Person 移至 Instructor,並將 EnrollmentDate 屬性從 Person 移至 Student

  4. Person 實體類型變成抽象型別。

  5. 使用下列兩個條件將 Instructor 實體類型對應至 Person 資料表:HireDate Is Not NullEnrollmentDate Is Null

  6. 使用下列兩個條件將 Student 實體類型對應至 Person 資料表:EnrollmentDate Is Not NullHireDate Is Null

必要條件

若要完成本逐步解說,必須建置 CourseManager 應用程式。如需詳細資訊和指示,請參閱 Entity Framework 快速入門。在建置此應用程式之後,您必須實作每個階層的資料表繼承,藉以修改其 EDM。然後,您就可以擴充應用程式的功能,以便顯示所選課程的註冊。

Note附註

因為本說明文件的許多逐步解說主題都從使用 CourseManager 應用程式開始,我們建議您為本逐步解說使用 CourseManager 應用程式的複本,而非編輯原始的 CourseManager 程式碼。

本逐步解說假設讀者具備以下基本能力:Visual Studio 和 .NET Framework 的使用能力,以及 Visual C# 或 Visual Basic 程式設計的能力。

實作每個階層的資料表繼承

在這個程序中,您將修改 SchoolModel EDM 的概念部分,以實作每個階層的資料表繼承。

若要實作每個階層的資料表繼承

  1. 在 Visual Studio 中開啟 CourseManager 方案。

  2. 按兩下 [方案總管] 中的 School.edmx 檔案。

    School.edmx 檔案隨即在 ADO.NET 實體資料模型設計工具 (Entity Designer) 中開啟。

  3. 以滑鼠右鍵按一下 Entity Designer 設計介面的空白空間,然後指向 [加入],再按一下 [實體]。

    [新增實體] 對話方塊隨即出現。

  4. 為 [實體名稱] 輸入 Instructor,然後從 [基底類型] 的下拉式清單中選取 Person

  5. 按一下 [確定]。

    在設計介面上便會建立並顯示新的實體類型。

  6. 重複步驟 3 到 5,但是在第二個步驟中為 [實體名稱] 輸入 Student

    現在,您在設計介面上就有兩個已顯示的實體類型,InstructorStudent。箭頭由新實體類型指向 Person 實體類型,這表示 Person 是新實體類型的基底類型。

  7. 以滑鼠右鍵按一下 Person 實體類型的 [HireDate] 屬性 (在 [純量屬性] 下方),然後選取 [剪下]。

  8. 以滑鼠右鍵按一下 Instructor 實體類型的 [純量屬性] 屬性,然後選取 [貼上]。

  9. 以滑鼠右鍵按一下 [HireDate] 屬性,然後選取 [屬性]。

  10. 在 [屬性] 視窗中將 [Nullable] 屬性設為 false

  11. 重複步驟 7 到 10,但是剪下 Person 實體類型的 [EnrollmentDate] 屬性,並將它貼至 Student 實體類型。

  12. 選取 Person 實體類型。在 [屬性] 視窗中將它的 [Abstract] 屬性設為 true

    隨即會出現一個訊息方塊,告知您定義實體類型為抽象將會移除那個類型的所有現有函式對應。按一下 [確定]。

    Note附註

    一般來說,您不必使用抽象型別來塑模每個階層的資料表繼承案例。本範例的抽象型別是用來示範其在 EDM 中的用法。

    Note附註

    本程序的剩餘步驟需要用到 [對應詳細資料] 視窗。如果沒有顯示這個視窗,請以滑鼠右鍵按一下設計介面,然後選取 [對應詳細資料]。

  13. 選取 Instructor 實體類型,然後按一下 [對應詳細資料] 視窗中的 [<加入資料表或檢視>]。

    [<加入資料表或檢視>] 欄位會變成所選實體可對應之資料表或檢視表的下拉式清單。

  14. 從下拉式清單中選取 Person

    [對應詳細資料] 視窗會更新成預設資料行對應和用於加入條件的選項。

  15. 按一下 [<加入函式>]。

    [<加入函式>] 欄位會變成可設定條件之資料行的下拉式清單。

  16. 從下拉式清單中選取 HireDate

    另一個 [<加入函式>] 欄位隨即出現。

  17. 在 [對應詳細資料] 視窗的 [運算子] 資料行中,從下拉式清單中選取 [Is]。

  18. 在 [屬性/值] 資料行中選取 [Not Null]。

  19. 按一下 [<加入函式>]。

  20. 從下拉式清單中選取 EnrollmentDate

  21. 在 [運算子] 資料行中,從下拉式清單中選取 [Is]。

  22. 在 [屬性/值] 資料行中選取 [Null]。

    Note附註

    如果在條件中使用值/屬性,則除非條件使用 [Is Null] 或 [Is Not Null] 比較,否則值/屬性不能是實體類型。

  23. Student 實體類型重複步驟 13 到 22,但是將條件設為 HireDate Is NullEnrollmentDate Is Not Null

現已實作每個階層的資料表繼承。

建構使用者介面

接下來,您將把按鈕加入至 CourseViewer 表單,它會載入並顯示 Enrollment 表單。然後,您將把兩個 ComboBox 控制項和一個 ListBox 控制項加入至 Enrollment 表單。第一個 ComboBox 可讓您選取科系。第二個 ComboBox 則可讓您根據第一個 ComboBox 中所選科系來選取課程。在 ListBox 控制項中會顯示所選課程的學生和講師清單。

若要建構使用者介面

  1. 以滑鼠右鍵按一下 [方案總管] 中的 CourseManager 專案,然後指向 [加入],再選取 [新增項目]。

    [加入新項目] 對話方塊隨即出現。

  2. 選取 [Windows Form],然後將表單的名稱設為 Enrollment.vb 或 Enrollment.cs (視使用的語言而定),再按一下 [加入]。

    新的表單隨即加入至專案並在表單設計工具中開啟。這個表單的名稱已設為 Enrollment,而且文字已設為 Enrollment

  3. ComboBox 控制項從 [工具箱] 拖曳至表單,並在 [屬性] 視窗中將它的名稱設為 departmentList

  4. 將另一個 ComboBox 控制項從 [工具箱] 拖曳至表單,並將它的名稱設為 courseList

  5. Listbox 控制項從 [工具箱] 拖曳至表單。在 [屬性] 視窗中將它的名稱設為 studentList

  6. 按兩下 [方案總管] 中的 CourseViewer.csCourseViewer.vb

    CourseViewer 表單的設計檢視隨即出現。

  7. Button 控制項從 [工具箱] 拖曳至 CourseViewer 表單。

  8. 在 [屬性] 視窗中將按鈕的名稱設為 viewEnrollment,然後將按鈕的文字設為 View Enrollment

  9. 按兩下 [viewEnrollment] 按鈕。

    CourseViewer 表單之程式碼後置(Code-Behind) 的檔案隨即開啟。

  10. 將下列程式碼加入至 viewEnrollment_click 事件處理常式:

    Dim enrollmentForm As New Enrollment()
    enrollmentForm.Visible = True
    
    Enrollment enrollmentForm = new Enrollment();
    enrollmentForm.Visible = true;
    

現已完成使用者介面。

查詢 EDM

在這個程序中,您將查詢 EDM,並將結果繫結至 Windows Form 控制項。如需將物件繫結至控制項的詳細資訊,請參閱將物件與控制項繫結 (Entity Framework)

若要查詢 EDM

  1. 表單設計工具中已開啟 Enrollment 表單時,按兩下 Enrollment 表單。

    Enrollment 表單之程式碼後置的檔案隨即開啟。

  2. 加入下列 using (C#) 或 Imports (Visual Basic) 陳述式,以便參考 EDM 命名空間 (Namespace):

    Imports System.Data.Objects
    Imports System.Data.Objects.DataClasses
    
    using System.Data.Objects;
    using System.Data.Objects.DataClasses;
    
  3. 將屬性加入至表示資料內容的 Enrollment 類別:

    ' Create an ObjectContext instance based on SchoolEntity.
    Private schoolContext As SchoolEntities
    
    // Create an ObjectContext instance based on SchoolEntity.
    private SchoolEntities schoolContext;
    
  4. Enrollment_Load 事件處理常式中加入程式碼,以便初始化物件內容,並將 ComboBox 控制項繫結至一個可傳回所有科系和相關課程資訊的查詢。

    ' 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.Department.Include("Course") _
        .OrderBy("it.Name")
    
    ' Bind the ComboBox control to the query, which is 
    ' executed during data binding.
    Me.departmentList.DataSource = departmentQuery _
    .Execute(MergeOption.OverwriteChanges)
    Me.departmentList.DisplayMember = "Name"
    
        // 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.Department.Include("Course")
                                    .OrderBy("it.Name");
    
        // Bind the ComboBox control to the query, which is
        // executed during data binding.
        this.departmentList.DataSource = departmentQuery
    .Execute(MergeOption.OverwriteChanges);
        this.departmentList.DisplayMember = "Name";
    
  5. 回到 Enrollment 表單的設計檢視,然後按兩下 departmentListComboBox 控制項。

    在程式碼後置的檔案中會建立 departmentList_SelectedIndexChanged 事件處理常式。

  6. 將程式碼加入至事件處理常式,以便將 courseListComboBox 控制項繫結至所選 DepartmentCourse 屬性。

    ' Get the object for the selected department
    Dim department As Department = CType(Me.departmentList _
            .SelectedItem, Department)
    
    ' Bind the ComboBox control Course properties of
    ' the selected Department.
    courseList.DataSource = department.Course
    courseList.DisplayMember = "Title"
    
    // Get the object for the selected department.
    Department department =
            (Department)this.departmentList.SelectedItem;
    
    // Bind the ComboBox control Course properties of 
    // the selected Department.
    courseList.DataSource = department.Course;
    courseList.DisplayMember = "Title";
    
  7. 回到 Enrollment 表單的設計檢視,然後按兩下 courseListComboBox 控制項。

    在程式碼後置的檔案中會建立 courseList_SelectedIndexChanged 事件處理常式。

  8. 將程式碼加入至事件處理常式,以便在 ListBox 中顯示學生清單。

    Me.studentList.Items.Clear()
    
    ' Get the CourseID from the selected Course.
    Dim course As Course = CType(Me.courseList.SelectedItem,  _
         Course)
    Dim courseId As Integer = course.CourseID
    
    ' Get all CourseGrade objects for the supplied CourseID
    Dim studentQuery As Course = schoolContext.Course.Where _
         ("it.CourseID = @courseID", New ObjectParameter _
          ("courseID", courseId)).Include("CourseGrade"). _
          FirstOrDefault()
    
    ' Get all students for each CourseGrade
    For Each cg As CourseGrade In studentQuery.CourseGrade
        cg.PersonReference.Load()
        studentList.Items.Add(cg.Person.LastName + ", " + _
                            cg.Person.FirstName)
    Next
    
    studentList.Items.Add(" ")
    
    ' Get all Instructor types for the supplied CourseID
    Dim instructorQuery As Course = schoolContext.Course. _
         Where("it.CourseID = @courseID", New ObjectParameter _
               ("courseID", courseId)).Include("Person") _
               .FirstOrDefault()
    
    ' Display each instructor for the specified Course
    For Each Instructor As Instructor In instructorQuery.Person
        Me.studentList.Items.Add("Instructor: " + Instructor. _
                        LastName + ", " + Instructor.FirstName)
    Next
    
    studentList.Items.Clear();
    
    // Get the CourseID from the selected Course.
    Course course = (Course)courseList.SelectedItem;
    int courseId = course.CourseID;
    
    // Get all CourseGrade types for the supplied CourseID
    Course studentQuery = schoolContext.Course.Where(
        "it.CourseID = @courseID", new ObjectParameter
            ("courseID", courseId)).Include("CourseGrade").
            FirstOrDefault();
    
    // Get all students for each CourseGrade
    foreach (CourseGrade cg in studentQuery.CourseGrade)
    {
        cg.PersonReference.Load();
        studentList.Items.Add(cg.Person.LastName + ", " +
            cg.Person.FirstName);
    }
    
    studentList.Items.Add(" ");
    
    // Get all Instructor types for the supplied CourseID
    Course instructorQuery = schoolContext.Course.Where(
        "it.CourseID = @courseID", new ObjectParameter
            ("courseID", courseId)).Include("Person").
            FirstOrDefault();
    
    // Display each instructor for the specified course.
    foreach (Instructor instructor in instructorQuery.Person.
        OfType<Instructor>())
    {
        studentList.Items.Add("Instructor: " + instructor.
            LastName + ", " + instructor.FirstName);
    }
    

現已完成應用程式。按 Ctrl + F5 執行應用程式,然後按一下 [View Enrollment] 按鈕載入 Enrollment 表單。隨即會在 ListBox 控制項中顯示所選課程的課程註冊和講師。

列出程式碼

本章節列出 Enrollment 表單之最終版本的程式碼後置檔案。

Imports System.Data.Objects
Imports System.Data.Objects.DataClasses

Public Class Enrollment

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

    Private Sub Enrollment_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.Department.Include("Course") _
            .OrderBy("it.Name")

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

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

        ' Bind the ComboBox control Course properties of
        ' the selected Department.
        courseList.DataSource = department.Course
        courseList.DisplayMember = "Title"
    End Sub

    Private Sub courseList_SelectedIndexChanged(ByVal sender As  _
            System.Object, ByVal e As System.EventArgs) Handles _
            courseList.SelectedIndexChanged
        Me.studentList.Items.Clear()

        ' Get the CourseID from the selected Course.
        Dim course As Course = CType(Me.courseList.SelectedItem,  _
             Course)
        Dim courseId As Integer = course.CourseID

        ' Get all CourseGrade objects for the supplied CourseID
        Dim studentQuery As Course = schoolContext.Course.Where _
             ("it.CourseID = @courseID", New ObjectParameter _
              ("courseID", courseId)).Include("CourseGrade"). _
              FirstOrDefault()

        ' Get all students for each CourseGrade
        For Each cg As CourseGrade In studentQuery.CourseGrade
            cg.PersonReference.Load()
            studentList.Items.Add(cg.Person.LastName + ", " + _
                                cg.Person.FirstName)
        Next

        studentList.Items.Add(" ")

        ' Get all Instructor types for the supplied CourseID
        Dim instructorQuery As Course = schoolContext.Course. _
             Where("it.CourseID = @courseID", New ObjectParameter _
                   ("courseID", courseId)).Include("Person") _
                   .FirstOrDefault()

        ' Display each instructor for the specified Course
        For Each Instructor As Instructor In instructorQuery.Person
            Me.studentList.Items.Add("Instructor: " + Instructor. _
                            LastName + ", " + Instructor.FirstName)
        Next
    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 Enrollment : Form
    {
        // Create an ObjectContext instance based on SchoolEntity.
        private SchoolEntities schoolContext;

        public Enrollment()
        {
            InitializeComponent();
        }

        private void Enrollment_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.Department.Include("Course")
                                        .OrderBy("it.Name");

            // Bind the ComboBox control to the query, which is
            // executed during data binding.
            this.departmentList.DataSource = departmentQuery
        .Execute(MergeOption.OverwriteChanges);
            this.departmentList.DisplayMember = "Name";
        }

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

            // Bind the ComboBox control Course properties of 
            // the selected Department.
            courseList.DataSource = department.Course;
            courseList.DisplayMember = "Title";
        }

        private void courseList_SelectedIndexChanged(object sender, 
            EventArgs e)
        {
            studentList.Items.Clear();

            // Get the CourseID from the selected Course.
            Course course = (Course)courseList.SelectedItem;
            int courseId = course.CourseID;

            // Get all CourseGrade types for the supplied CourseID
            Course studentQuery = schoolContext.Course.Where(
                "it.CourseID = @courseID", new ObjectParameter
                    ("courseID", courseId)).Include("CourseGrade").
                    FirstOrDefault();

            // Get all students for each CourseGrade
            foreach (CourseGrade cg in studentQuery.CourseGrade)
            {
                cg.PersonReference.Load();
                studentList.Items.Add(cg.Person.LastName + ", " +
                    cg.Person.FirstName);
            }

            studentList.Items.Add(" ");

            // Get all Instructor types for the supplied CourseID
            Course instructorQuery = schoolContext.Course.Where(
                "it.CourseID = @courseID", new ObjectParameter
                    ("courseID", courseId)).Include("Person").
                    FirstOrDefault();

            // Display each instructor for the specified course.
            foreach (Instructor instructor in instructorQuery.Person.
                OfType<Instructor>())
            {
                studentList.Items.Add("Instructor: " + instructor.
                    LastName + ", " + instructor.FirstName);
            }
        } 
    }
}

後續的步驟

您已成功在 EDM 中實作每個階層的資料表繼承。如需如何使用每個階層的資料表繼承來定義 EDM 的詳細資訊,請參閱 HOW TO:使用每個階層的資料表繼承來定義模型 (Entity Framework)。如需如何使用 Entity Framework 建置應用程式的詳細資訊,請參閱程式設計指南 (Entity Framework)

另請參閱

其他資源

ADO.NET 實體資料模型設計工具案例
Entity Data Model 工具工作