逐步解說:對應每個類型的資料表繼承

本主題示範如何在 Entity Data Model (EDM) 中修改概念模型以實作每個類型的資料表繼承。每個類型的資料表繼承會在資料庫中使用個別資料表來維護繼承階層架構 (Inheritance Hierarchy) 中每一個類型的非繼承屬性和索引鍵屬性。如需以 EDM 實作階層架構的詳細資訊,請參閱繼承 (EDM)

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

在 CourseManager 應用程式中,會將 CourseOnlineCourseOnsiteCourse 實體類型對應至相同名稱的資料表。因為 OnlineCourseOnsiteCourse 實體類型包含的資訊對於兩個課程類型是唯一的,所以可以將它們變更為從 Course 實體類型繼承。下列步驟概述如何在此案例中實作每個類型的資料表繼承 (本主題稍後的程序有提供更詳細的資訊)。

  1. 刪除 OnlineCourse 實體類型與 Course 實體類型之間的關聯。刪除 OnsiteCourse 實體類型與 Course 實體類型之間的關聯。這些關聯會被繼承階層架構實作取代。

  2. OnlineCourseOnsiteCourse 實體類型刪除 CourseID 索引鍵屬性。這個屬性將會繼承自 Course 實體類型。

  3. Course 實體類型設為 OnlineCourseOnsiteCourse 實體類型的基底類型。

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

  5. OnlineCourseOnsiteCourse 實體類型的繼承 CourseID 屬設為適當的資料行。

必要條件

若要完成本逐步解說,必須先建置 CourseManager 應用程式。如需詳細資訊和指示,請參閱 Entity Framework 快速入門。您必須實作每個類型的資料表繼承,藉以修改 CourseManager 應用程式中使用的 EDM。然後,您就可以擴充應用程式的功能,以便個別顯示所選科系的線上和現場課程。

Note附註

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

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

實作每個類型的資料表繼承

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

若要實作每個類型的資料表繼承

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

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

    School.edmx 檔案隨即在 Entity Data Model Designer (Entity Designer) 中開啟。

  3. 以滑鼠右鍵按一下 OnlineCourse 實體類型,然後選取 [屬性]。

  4. 在 [屬性] 視窗中將 [基底類型] 屬性設為 Course

  5. OnsiteCourse 實體類型重複步驟 3 到 4。

  6. 以滑鼠右鍵按一下 OnlineCourseCourse 實體類型之間的關聯 (關聯線)。選取 [刪除]。

  7. 以滑鼠右鍵按一下 OnsiteCourseCourse 實體類型之間的關聯。選取 [刪除]。

  8. 以滑鼠右鍵按一下 OnlineCourse 實體類型的 [CourseID] 屬性,然後選取 [刪除]。

  9. 以滑鼠右鍵按一下 OnsiteCourse 實體類型的 [CourseID] 屬性,然後選取 [刪除]。

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

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

    Note附註

    因為 Course 實體類型現已變更為抽象型別,原始 CourseManager 應用程式的更新功能將不會運作。

  11. 以滑鼠右鍵按一下 OnlineCourse 實體類型,然後選取 [資料表對應]。

    [對應詳細資料] 視窗隨即出現。

  12. 按一下對應至 CourseID 資料行的 [值/屬性] 欄位。

    [值/屬性] 欄位會變成可供對應至對應欄位之屬性的下拉式清單。

  13. 從下拉式清單中選取 CourseID

  14. OnsiteCourse 實體類型重複步驟 11 到 13。

現已實作每個類型的資料表繼承。

建構使用者介面

接下來,您將把按鈕加入至 CourseViewer 表單,它會載入並顯示 CourseDiscrimForm 表單。然後,您將加入兩個 DataGridView 控制項,用於顯示 OnsiteCoursesOnlineCourses。最後,您將把 DataGridView 繫結至 BindingSource 控制項。如需將物件繫結至控制項的詳細資訊,請參閱將物件與控制項繫結 (Entity Framework)

若要建構使用者介面

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

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

  2. 選取 [Windows Form],然後按一下 [加入]。

    新的表單隨即加入至專案並在表單設計工具中開啟。

  3. 在 [屬性] 視窗中將表單的名稱設為 CourseDiscriminator

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

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

  5. DataGridView 控制項從 [工具箱] 拖曳至表單,並將它的名稱設為 onsiteGridView

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

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

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

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

  9. 在 [屬性] 視窗中將 Button 的名稱設為 viewDiscriminator,然後將按鈕的文字設為 Online vs. Onsite

  10. 按兩下 viewDiscriminatorButton

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

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

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

現已完成此表單的使用者介面。

查詢 EDM

在這個程序中,您將查詢 EDM,並將結果繫結至 Windows Form 控制項。

若要查詢 EDM

  1. 在表單設計工具中開啟 CourseDiscriminator 表單。

  2. BindingSource 控制項從 [工具箱] 拖曳至表單。

  3. 在 [屬性] 視窗中將 BindingSource 的名稱設為 onsiteBindingSource

  4. 在 [屬性] 視窗中按一下 [DataSource] 屬性旁邊的欄位。

    該欄位會變成可用資料來源的下拉式清單。

  5. 按一下 [加入專案資料來源]。

    [資料來源組態精靈] 的 [選擇資料來源類型] 視窗隨即開啟。

  6. 在 [應用程式要從何處取得資料] 方塊中選取 [物件]。

  7. 按一下 [下一步]。

    [選取您要繫結的目標物件] 視窗隨即開啟。會顯示可用資源的最上層樹狀節點。

  8. 展開 CourseManager 節點,然後展開 SchoolModel (C#) 或 CourseManager.SchoolModel (Visual Basic) 節點。

  9. 選取 OnsiteCourse,然後按一下 [完成]。

  10. 重複步驟 2 到 9,但是將 BindingSource 控制項命名為 OnlineBindingSource,並將它繫結至 OnlineCourse 物件。

  11. 以滑鼠右鍵按一下 OnsiteGridView 控制項,然後選取 [屬性]。

  12. 在 [屬性] 視窗中按一下 [DataSource] 屬性旁邊的欄位。

    該欄位會變成可用資料來源的下拉式清單。

  13. 選取 OnsiteBindingSource

  14. OnlineGridView 重複步驟 11 到 13,但是將 [DataSouce] 屬性設為 OnlineBindingSource

    Note附註

    OfType 方法會傳回 DataGridView 控制項無法在執行階段產生資料行的列舉型別 (Enumeration)。若要在這個範例中顯示想要用的資訊,必須根據所要繫結的類別,在設計階段透過 BindingSource 控制項設定 DataGridView 控制項的資料來源。

  15. 按兩下 CourseDiscriminator 表單。

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

  16. 加入下列 using (C#) 或 Imports (Visual Basic) 陳述式 (Statement),以便參考您從 School 資料庫建立的模型,以及實體命名空間 (Namespace)。

    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 事件處理常式中加入程式碼,以便初始化物件內容,並將 departmentList 控制項繫結至一個可傳回 Department 資訊的查詢。

    ' 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.
    departmentList.DataSource = departmentQuery _
    .Execute(MergeOption.OverwriteChanges)
    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";
    
  19. 回到 CourseDiscriminator 表單的設計工具檢視,然後按兩下 departmentListComboBox 控制項。

    程式碼後置的檔案隨即開啟。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.Course _
        .OfType(Of OnsiteCourse)()
    onlineBindingSource.DataSource = department.Course _
        .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.Course
        .OfType<OnsiteCourse>();
    onlineBindingSource.DataSource = department.Course
        .OfType<OnlineCourse>();
    

現已完成應用程式。按 Ctrl + F5 執行應用程式,然後按一下 [Onsite vs. Online] 按鈕載入 CourseDiscriminator 表單。在 DataGridView 控制項中會顯示所選科系的 OnsiteCoursesOnlineCourses

列出程式碼

本章節列出 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.Department.Include("Course") _
                .OrderBy("it.Name")

        ' Bind the ComboBox control to the query, which is
        ' executed during data binding.
        departmentList.DataSource = departmentQuery _
        .Execute(MergeOption.OverwriteChanges)
        departmentList.DisplayMember = "Name"
    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.Course _
            .OfType(Of OnsiteCourse)()
        onlineBindingSource.DataSource = department.Course _
            .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.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 selected department object.
            Department department = (Department)this.departmentList
                .SelectedItem;

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

後續的步驟

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

另請參閱

其他資源

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