設計工具 TPH 繼承

這個逐步解說示範如何使用 Entity Framework Designer (EF Designer) 在概念模型中實作每個階層資料表 (TPH) 繼承。 TPH 繼承使用一個資料庫資料表來維護繼承階層中所有實體類型的資料。

在本逐步解說中,我們將 Person 資料表對應至三種實體類型:Person(基底類型)、學生(衍生自 Person),以及 Instructor(衍生自 Person)。 我們將從資料庫建立概念模型(Database First),然後使用 EF 設計工具改變模型來實作 TPH 繼承。

您可以使用 Model First 對應至 TPH 繼承,但您必須撰寫複雜的資料庫產生工作流程。 接著,您會將此工作流程指派給 EF Designer 中的 [資料庫產生工作流程 ] 屬性。 較簡單的替代方法是使用 Code First。

其他繼承選項

資料表每一類型 (TPT) 是另一種繼承類型,其中資料庫中的個別資料表會對應至參與繼承的實體。  如需如何使用 EF 設計工具對應資料表個別類型繼承的資訊,請參閱 EF 設計工具 TPT 繼承

Entity Framework 執行時間支援資料表個別類型繼承(TPC)和混合繼承模型,但 EF 設計工具不支援。 如果您想要使用 TPC 或混合繼承,您有兩個選項:使用 Code First,或手動編輯 EDMX 檔案。 如果您選擇使用 EDMX 檔案,[對應詳細資料] 視窗將會進入「安全模式」,而且您將無法使用設計工具來變更對應。

必要條件

若要完成這個逐步解說,您將需要:

設定專案

  • 開啟 Visual Studio 2012。
  • 選取 [檔案- > 新增 - 專案] >
  • 在左窗格中,按一下 [Visual C# ],然後選取 主控台 範本。
  • 輸入 TPHDBFirstSample 作為名稱。
  • 選取 [確定]。

建立模型

  • 以滑鼠右鍵按一下方案總管中的專案名稱,然後選取 [ 新增 - > 新增專案 ]。
  • 從左側功能表中選取 [資料 ],然後在 [範本] 窗格中選取 [ADO.NET 實體資料模型 ]。
  • 輸入 TPHModel.edmx 以取得檔案名,然後按一下 [ 新增 ]。
  • 在 [選擇模型內容] 對話方塊中,選取 [從資料庫 產生],然後按 [下一步 ]。
  • 按一下 [ 新增連線。 在 [連線ion 屬性] 對話方塊中,輸入伺服器名稱 (例如 , localdb)\mssqllocaldb ),選取驗證方法,輸入 School 以取得資料庫名稱,然後按一下 [ 確定 ]。 [選擇您的資料連線] 對話方塊會使用您的資料庫連線設定來更新。
  • 在 [選擇資料庫物件] 對話方塊的 [資料表] 節點底下,選取 [ 人員 ] 資料表。
  • 按一下完成

[實體設計工具] 會顯示為編輯模型提供設計介面。 您在 [選擇資料庫物件] 對話方塊中選取的所有物件都會新增至模型。

這就是 Person 資料表在資料庫中的外觀。

Person Table 

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

Person 資料表具有 「歧視性 」資料行,其可以有兩個值之一:「Student」 和 「Instructor」。 根據 Person 資料表將對應至 Student 實體或 Instructor 實體的值 Person 資料表也有兩個數據行 HireDate 和 EnrollmentDate ,這必須 可為 Null,因為人員不能同時是學生和講師(至少在此逐步解說中不是)。

新增實體

  • 新增實體。 若要這樣做,請以滑鼠右鍵按一下 Entity Framework 設計工具設計介面的空白空間,然後選取 [ 新增 > 實體 ]。
  • 輸入 機構名稱 Instructor ,然後從基底類型的 下拉式清單中 選取 [人員 ]。
  • 按一下 [確定]
  • 新增另一個新實體。 輸入 Student 以取得 機構名稱 ,然後從 [基底類型 ] 的下拉式清單中 選取 [人員 ]。

兩個新的實體類型已新增至設計介面。 箭號會從新的實體類型指向 Person 實體類型;這表示 Person 是新實體類型的基底類型。

  • 以滑鼠右鍵按一下 Person 實體的 HireDate 屬性。 選取 [ 剪下 ](或使用 Ctrl-X 鍵)。
  • 滑鼠右鍵按一下 Instructor 實體,然後選取 [貼上 ] (或使用 Ctrl-V 鍵)。
  • 以滑鼠右鍵按一下 HireDate 屬性,然後選取 [ 屬性 ]。
  • 在 [ 屬性] 視窗中,將 Nullable 屬性設定為 false
  • 以滑鼠右鍵按一下 Person 實體的 EnrollmentDate 屬性。 選取 [ 剪下 ](或使用 Ctrl-X 鍵)。
  • 滑鼠右鍵按一下 Student 實體,然後選取 [貼上] (或使用 Ctrl-V 鍵)。
  • 選取 EnrollmentDate 屬性,並將 Nullable 屬性設定 false
  • 選取 [ 人員 ] 實體類型。 在 [ 屬性] 視窗中,將其 Abstract 屬性設定為 true
  • Person 刪除「歧視性 」屬性。 應該刪除的原因如下一節所述。

對應實體

  • 滑鼠右鍵按一下 Instructor ,然後選取 [資料表對應]。 [對應詳細資料] 視窗中已選取 Instructor 實體。

  • 按一下 < [對應詳細 資料] 視窗中的 [新增資料表] 或 [檢視 > ]。 [ < 新增資料表] 或 [檢 > 視] 欄位會變成資料表或檢視的下拉式清單,可供選取的實體對應。

  • 從下拉式清單中選取 [ 人員 ]。

  • [ 對應詳細資料 ] 視窗會更新為預設資料行對應,以及新增條件的選項。

  • 按一下 [ 新增條件 > ]。 < [ < 新增條件 > ] 欄位會變成可設定條件之資料行的下拉式清單。

  • 從下拉式清單中選取 [歧視性 ]。

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

  • 在 [ 值/屬性 ] 資料行中,輸入 Instructor 。 最終結果看起來應該像這樣:

    Mapping Details

  • 針對 Student 實體類型重複這些步驟,但使條件等於 Student 值。
    我們想要移除 Discriminator 屬性的原因是您無法多次對應資料表資料行。 此資料行將用於條件式對應,因此也無法用於屬性對應。 如果條件使用 Is Null 或 Is Not Null 比較,則兩者都可以使用的唯一 方式。

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

Final TPH

使用模型

開啟定義 Main 方法的 Program.cs 檔案。 將下列程式碼貼到 Main 函式中。 程式碼會執行三個查詢。 第一個查詢會帶回所有 Person 物件。 第二個查詢會使用 OfType 方法傳回 Instructor 物件。 第三個查詢會使用 OfType 方法傳回 Student 物件。

    using (var context = new SchoolEntities())
    {
        Console.WriteLine("All people:");
        foreach (var person in context.People)
        {
            Console.WriteLine("    {0} {1}", person.FirstName, person.LastName);
        }

        Console.WriteLine("Instructors only: ");
        foreach (var person in context.People.OfType<Instructor>())
        {
            Console.WriteLine("    {0} {1}", person.FirstName, person.LastName);
        }

        Console.WriteLine("Students only: ");
        foreach (var person in context.People.OfType<Student>())
        {
            Console.WriteLine("    {0} {1}", person.FirstName, person.LastName);
        }
    }