消費者入門 Entity Framework 4.0 Database First 和 ASP.NET 4 Web Form - 第 6 部分

By Tom Dykstra

Contoso University 範例 Web 應用程式示範如何使用 Entity Framework 4.0 和 Visual Studio 2010 建立 ASP.NET Web Forms應用程式。 如需教學課程系列的相關資訊,請參閱 系列中的第一個教學課程

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

在上一個教學課程中,您已藉由新增和刪除關聯性,以及新增與現有實體有關聯性的新實體,來處理相關資料。 本教學課程將示範如何在資料模型中實作繼承。

在物件導向程式設計中,您可以使用繼承,更輕鬆地處理相關的類別。 例如,您可以建立 Instructor 衍生自基類的 PersonStudent 類別。 您可以在 Entity Framework 中的實體之間建立相同種類的繼承結構。

在本教學課程的這個部分中,您將不會建立任何新的網頁。 相反地,您會將衍生實體新增至資料模型,並修改現有的頁面以使用新的實體。

資料表個別階層與資料表個別類型繼承

資料庫可以將相關物件的相關資訊儲存在一個資料表或多個資料表中。 例如,在 School 資料庫中, Person 資料表包含單一資料表中學生和講師的相關資訊。 部分資料行僅適用于講師 (HireDate) 、部分僅套用至學生 (EnrollmentDate) ,有些則同時套用至 (LastNameFirstName) 。

image11

您可以設定 Entity Framework 來建立 InstructorStudent 繼承自實體的 Person 實體。 從單一資料庫資料表產生實體繼承結構的此模式稱為每個階層的 資料表 (TPH) 繼承。

針對課程, School 資料庫會使用不同的模式。 線上課程和現場課程會儲存在不同的資料表中,每個課程都有指向資料表的 Course 外鍵。 這兩個課程類型的通用資訊只會儲存在資料表中 Course

image12

您可以設定 Entity Framework 資料模型, OnlineCourse 讓 和 OnsiteCourse 實體繼承自 Course 實體。 此模式會從每個類型的個別資料表產生實體繼承結構,每個個別資料表都會參考回儲存所有 類型 通用資料的資料表, (TPT) 繼承。

TPH 繼承模式通常會在 Entity Framework 中提供比 TPT 繼承模式更好的效能,因為 TPT 模式可能會導致複雜的聯結查詢。 本逐步解說示範如何實作 TPH 繼承。 您將執行下列步驟來執行此動作:

  • 建立 Instructor 衍生自 Person 的 實體 Student 類型。
  • 將與衍生實體相關的屬性從 Person 實體移至衍生實體。
  • 在衍生型別中設定屬性的條件約束。
  • Person使實體成為抽象實體。
  • 將每個衍生實體對應至 Person 資料表,其中包含指定如何判斷資料列是否 Person 代表該衍生型別的條件。

新增 Instructor 和 Student 實體

開啟 SchoolModel.edmx 檔案,以滑鼠右鍵按一下設計工具中的未配置區域,選取 [ 新增],然後選取 [實體]。

image01

在 [ 新增實體 ] 對話方塊中,將實體 Instructor 命名為 ,並將其 [基底類型 ] 選項設定為 Person

image02

按一下 [確定]。 設計工具會 Instructor 建立衍生自實體的 Person 實體。 新的實體還沒有任何屬性。

image03

重複此程式,以建立 Student 也衍生自 Person 的實體。

只有講師有雇用日期,因此您必須將該屬性從 Person 實體 Instructor 移至實體。 在實體中 PersonHireDate ,以滑鼠右鍵按一下 屬性,然後按一下 [ 剪下]。 然後在實體中的 [ 屬性 ] Instructor 上按一下滑鼠右鍵,然後按一下 [ 貼上]。

image04

實體的 Instructor 雇用日期不可為 Null。 以滑鼠右鍵按一下 HireDate 屬性,按一下 [ 屬性],然後在 [ 屬性 ] 視窗中變更 NullableFalse

image05

重複此程式,將 EnrollmentDate 屬性從 Person 實體 Student 移至實體。 請確定您也針對 屬性設定 NullableFalseEnrollmentDate

現在,實體 Person 只有通用 Instructor 的屬性和 Student (實體,除了您不移動的導覽屬性之外,您不會移動) ,實體只能當做繼承結構中的基底實體使用。 因此,您必須確保它永遠不會被視為獨立實體。 以滑鼠右鍵按一下 Person 實體,選取 [ 屬性],然後在 [ 屬性 ] 視窗中,將 Abstract 屬性的值變更為 True

image06

將講師和學生實體對應至人員資料表

現在您必須告訴 Entity Framework 如何區分 Instructor 資料庫中的 和 Student 實體。

以滑鼠右鍵按一下實體, Instructor 然後選取 [ 資料表對應]。 在 [ 對應詳細資料] 視窗中,按一下 [ 新增資料表] 或 [檢視 ],然後選取 [ 人員]。

image07

按一下 [新增條件],然後選取 [HireDate]。

image09

運算子 變更為 Is並將 Value / 屬性 變更為 Not Null

image10

重複實體的程式 Students ,指定此實體在資料行不是 Null 時 EnrollmentDate 對應至 Person 資料表。 然後儲存並關閉資料模型。

建置專案,以建立新的實體作為類別,並在設計工具中提供它們。

使用講師和學生實體

當您建立使用學生和講師資料的網頁時,您會將資料系結至 Person 實體集,並篩選 HireDateEnrollmentDate 屬性,以將傳回的資料限制給學生或講師。 不過,現在當您將每個資料來源控制項系結至 Person 實體集時,您可以指定只 Student 選取或 Instructor 實體類型。 由於 Entity Framework 知道如何區分實體集中的學生和講師 Person ,因此您可以移除 Where 手動輸入的屬性設定來執行此動作。

在 Visual Studio Designer中,您可以指定控制項應該在精靈的EntityTypeFilter下拉式方 Configure Data Source 塊中選取的實體類型 EntityDataSource ,如下列範例所示。

image13

在 [ 屬性 ] 視窗中,您可以移除 Where 不再需要的子句值,如下列範例所示。

image14

不過,因為您已將控制項的標記 EntityDataSource 變更為使用 ContextTypeName 屬性,所以您無法在已建立的控制項上 EntityDataSource 執行 [設定資料來源精靈]。 因此,您將改為變更標記來進行必要的變更。

開啟 Students.aspx 頁面。 在 控制項中 StudentsEntityDataSourceWhere ,移除 屬性並新增 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 控制項只會選取指定的實體類型。 如果您想要同時 Student 擷取 和 Instructor 實體類型,則不會設定此屬性。 (只有在您使用控制項進行唯讀資料存取時,您才能選擇擷取具有一個 EntityDataSource 控制項的多個實體類型。如果您使用 EntityDataSource 控制項來插入、更新或刪除實體,而且它系結至的實體集可以包含多個類型,則只能使用一個實體類型,而且您必須設定此屬性。)

重複控制項的程式 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

更新您在先前教學課程中建立的下列頁面,使其使用新的 StudentInstructor 實體,而不是 Person 實體,然後執行它們以確認它們如先前一樣運作:

  • StudentsAdd.aspx中,將 新增 EntityTypeFilter="Student"StudentsEntityDataSource 控制項。 標記現在會類似下列範例:

    <asp:EntityDataSource ID="StudentsEntityDataSource" runat="server" 
            ContextTypeName="ContosoUniversity.DAL.SchoolEntities" EnableFlattening="False"
            EntitySetName="People" EntityTypeFilter="Student"
            EnableInsert="True" 
        </asp:EntityDataSource>
    

    image16

  • About.aspxStudentStatisticsEntityDataSource ,新增 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 應用程式中不需要變更任何程式碼。 新增 InstructorStudent 實體的另一個優點是,您的程式碼比參考 Person 實際學生或講師的物件更容易瞭解。

您現在已瞭解如何在 Entity Framework 中實作繼承模式。 在下列教學課程中,您將瞭解如何使用預存程式,以更充分掌控 Entity Framework 存取資料庫的方式。