繼承 (EDM)
在 實體資料模型 (EDM) 中,繼承 (Inheritance) 允許衍生型別 (Derived Type) 擴充另一個型別的功能。
一般而言,應用程式所使用的模型包含許多不同的型別。某些實體類型會建立個別概念的模型,例如商務應用程式中的客戶和訂單****。這些資料型別不會共用任何成員,但是它們具有彼此更相似的其他型別。例如,請考量客戶和員工型別。雖然這些型別會建立不同概念的模型,但是它們具有基礎共通性:這兩個型別都代表商務關聯性 (Relationship) 所涉及的人員,而且它們都含有儲存名稱、地址和電話號碼等資訊的屬性。
EDM 繼承允許某個型別衍生自另一個型別。例如,Employee
和 Customer
都可以繼承自 Contact
型別。在此情況下,Contact
稱為基底型別。Employee
和 Customer
則稱為衍生型別 (Derived Type)。
繼承的動作不侷限於單一層級:衍生型別可能是另一個實體類型的基底型別。例如,Employee
是 Manager
的基底型別、Customer
是 PreferredCustomer
的基底型別,依此類推。如此一來,就會建立繼承階層。
如同 Common Language Runtime (CLR),EDM 系統僅支援資料型別的單一繼承。實體類型只能直接從某個超級型別繼承屬性。
附註 |
---|
由於 EDM 系統不會實作方法,因此不支援方法繼承。在 EDM 中,Helper 方法是在部分類別中實作。如需詳細資訊,請參閱 Helper 方法 (EDM)。 |
繼承範例
下列範例將針對先前描述的繼承階層說明部分概念結構定義語言 (CSDL) 規格:
<EntityType Name="Contact">
<Key>
<PropertyRef Name="ContactId" />
</Key>
<Property Name="ContactId" Type="Int32" Nullable="false" />
<Property Name="Name" Type="String" />
<Property Name="Address" Type="Address" />
<Property Name="Phone" Type="String" />
</EntityType>
<EntityType Name="Customer" BaseType="Contact">
<Property Name="CustomerID" Type="String" />
<Property Name="CompanyName" Type="String" />
</EntityType>
<EntityType Name="PreferredCustomer" BaseType="Customer">
<Property Name="PreferenceCode" Type="String" />
<Property Name="CreditLimit" Type="Decimal" />
</EntityType>
<!-- Similar Declarations for Employee and Manager -->
繼承的其中一項目的是要在多個型別之間共用基本結構。使用繼承的另一項原因則是擴充性。即使已經在應用程式中實作和部署繼承階層之後,開發人員仍然可以透過繼承擴充這些型別。
多型 (Polymorphism) 或值替代性的物件導向程式設計概念會取決於繼承。衍生資料型別的每個執行個體 (Instance) 也是其基底類型的執行個體。例如,如果 Manager
衍生自 Employee
,則 Manager
的每個執行個體也是 Employee
的執行個體。當您查詢所有員工 (基底類型) 時,也會取得所有經理 (衍生型別)。
如需繼承的詳細資訊,請參閱 HOW TO:使用每個類型的資料表繼承來定義模型和 HOW TO:使用每個階層的資料表繼承來定義模型 (Entity Framework)。
繼承實作
CSDL 中所定義的繼承階層必須在存放建立於 EDM 模型之應用程式資料的資料庫資料表中實作。有許多方式可以在資料庫資料表中結構化繼承階層中的型別。
在所有實作 (Implementation) 中,基底和衍生型別的索引鍵結構必須完全相同。也就是說,如果 Customer
型別衍生自 Person
型別,則 Customer
和 Person
型別都必須指定相同的索引鍵屬性。
在繼承的多重資料表實作中,相同的值會指派給多份資料表中的索引鍵屬性,以便將衍生型別識別為祖系型別的執行個體。
例如,在此對應規格中,繼承的實作可以使用 EntityTypeMapping 的 IsTypeOf<T> 指示器來指定 Customer
型別也是基底型別 Person 的型別。此外,概念和儲存結構描述的 EntityType 中都有一個 BaseType 屬性,可用來指定衍生實體的基底型別。
每個階層的資料表模型
以每個階層的資料表模型為基礎的繼承會使用相同的資料庫資料表來指定階層中的多重型別。在此模型中,對應規格的明確條件會識別繼承階層中的型別。
資料表中含有可區別每個型別的鑑別子資料行,而且該條件會參考每個型別之資料行的指派值。例如,該條件可能會指定 EntityType
資料行的值等於 P
(代表 Person 型別) 或 C
(代表 Customer 型別)。
下列對應範例會說明 Customer
和 Person
型別的條件式對應。
<?xml version="1.0" encoding="utf-8"?>
<Mapping Space="C-S"
xmlns:cdm="urn:schemas-microsoft-com:windows:storage:mapping:CS"
xmlns="urn:schemas-microsoft-com:windows:storage:mapping:CS">
<EntityContainerMapping>
<EntitySetMapping Name="CCustomer1">
<EntityTypeMapping TypeName="CNorthwind.CCustomer">
<MappingFragment StoreEntitySet="SParty1">
<EntityKey>
<ScalarProperty Name="PartyID" ColumnName="PartyID" />
</EntityKey>
<ScalarProperty Name="PartyName" ColumnName="PartyName" />
<ScalarProperty Name="PartyTitle" ColumnName="Title" />
<ScalarProperty Name="ContactName" ColumnName="ContactName" />
<Condition Value="C" ColumnName="EntityType" />
</MappingFragment>
</EntityTypeMapping>
</EntitySetMapping>
<EntitySetMapping Name="CSupplier1">
<EntityTypeMapping TypeName="CNorthwind.CSupplier">
<MappingFragment StoreEntitySet="SParty1">
<EntityKey>
<ScalarProperty Name="PartyID" ColumnName="PartyID" />
</EntityKey>
<ScalarProperty Name="PartyName" ColumnName="PartyName" />
<ScalarProperty Name="PartyTitle" ColumnName="Title" />
<ScalarProperty Name="HomePage" ColumnName="HomePage" />
<Condition Value="S" ColumnName="EntityType" />
</MappingFragment>
</EntityTypeMapping>
</EntitySetMapping>
</EntityContainerMapping>
</Mapping>
每個類型的資料表模型
在以每個類型的資料表模型為基礎的繼承中,基底型別或祖系型別會存放在某個資料表中,而其他資料表則用於衍生型別。衍生型別特有的欄位只會出現在代表衍生型別的資料表中。此繼承模型中實體的對應會跨越許多實體資料表。資料表中某個資料列的存在與否會區別階層的型別。相同的索引鍵值會指派給所有資料表中的索引鍵屬性。
EntityType 的 BaseType 屬性可在概念和儲存結構描述中用來指定從基底型別繼承。對應規格中的 IsTypeOf<T> 指示器可用來指定基底型別並刪除重複的對應語法。
下列對應範例會說明兩個個別對應 Customer
和 Person
型別。EntityTypeMapping 項目的 ****TypeName 屬性 (Attribute) 會區別 Person
和 Customer
型別。每個型別都有一份資料表。Customer
實體類型和資料表包含 NumYears
屬性 (Property) 以及沒有包含在基底型別中的資料行。
<?xml version="1.0" encoding="utf-8"?>
<Mapping Space="C-S"
xmlns:cdm="urn:schemas-microsoft-com:windows:storage:mapping:CS"
xmlns="urn:schemas-microsoft-com:windows:storage:mapping:CS">
<EntityContainerMapping EntityContainerName="CNorthwind.LOBData">
<EntitySetMapping Name="Person1">
<EntityTypeMapping TypeName="CNorthwind.Person">
<MappingFragment StoreEntitySet="Person">
<ScalarProperty Name="PersonID" ColumnName="PersonID" />
<ScalarProperty Name="Name" ColumnName="Name" />
</MappingFragment>
</EntityTypeMapping>
<EntityTypeMapping TypeName="CNorthwind.Customer">
<MappingFragment StoreEntitySet="Customer">
<ScalarProperty Name="PersonID" ColumnName="PersonID" />
<ScalarProperty Name="Name" ColumnName="Name" />
<ScalarProperty Name="NumYears" ColumnName="NumYears" />
</MappingFragment>
</EntityTypeMapping>
</EntitySetMapping>
</EntityContainerMapping>
</Mapping>
另請參閱
工作
HOW TO:使用每個類型的資料表繼承來定義模型 (Entity Framework)
HOW TO:使用每個階層的資料表繼承來定義模型 (Entity Framework)
概念
Entity Data Model 類型
Helper 方法 (EDM)
Entity Data Model 繼承 (應用程式案例)