Inheritance (EDM)

In the Entity Data Model (EDM), inheritance permits a derived type to extend the features of another type.

Typically, the model used by an application includes many different types. Some entity types model separate concepts, such as customer and order in a business application. These data types do not share any members, but there are other types that are more similar to each other. For example, consider the customer and employee types. Although these types model different concepts, there is underlying commonality: Both represent people involved in business relationships and both include properties to store information such as name, address, and telephone number.

EDM inheritance permits one type to be derived from another type. For example, Employee and Customer can both inherit from the Contact type. In this case, Contact is called the base type. Employee and Customer are called derived types.

Inheritance does not have to stop at a single level: It is possible for a derived type to be the base type of another entity type. For example, Employee is a base type of Manager; Customer is a base type of PreferredCustomer, and so on. In this manner, inheritance hierarchies are built.

Like the common language runtime (CLR), the EDM system supports only single inheritance of data types. An entity type can only directly inherit properties from one super-type.

Note

Because the EDM system does not implement methods, method inheritance is not supported. In the EDM, helper methods are implemented in partial classes. For more information, see Helper Methods (EDM).

Inheritance Examples

The following example shows a partial conceptual schema definition language (CSDL) specification for the inheritance hierarchy described earlier:

  <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 -->

One purpose of inheritance is to share a fundamental structure among multiple types. Another reason to use inheritance is extensibility. Even after an inheritance hierarchy has been implemented and deployed in an application, developers can extend the types through inheritance.

The object-oriented programming concept of polymorphism or value substitutability depends on inheritance. Every instance of a derived data type is also an instance of its base type. For example, if Manager is derived from Employee, every instance of Manager is also an instance of an Employee. When you query for all employees (the base type), you also get all managers (the derived type).

For more information on inheritance, see How to: Define a Model with Table-per-Type Inheritance and How to: Define a Model with Table-per-Hierarchy Inheritance (Entity Framework).

Inheritance Implementation

An inheritance hierarchy as defined in CSDL must be implemented in the database tables that store data for an application built on the EDM model. There are several ways the types in an inheritance hierarchy can be structured in the database tables.

In all implementations, the key structure of base and derived types must be identical. That is, if a Customer type is derived from the Person type, both Customer and Person types must specify the same key property or properties.

In multi-table implementations of inheritance, the same value is assigned to the key property in more than one table to identify derived types as instances of ancestor types.

In the mapping specification, implementations of inheritance can use the IsTypeOf<T> indicator in the EntityTypeMapping to specify that, for example, the Customer type is also a type of the base type Person. There is also a BaseType attribute of the EntityType in both the conceptual and storage schemas that can be used to designate the base type of a derived entity.

Table-per-Hierarchy Model

Inheritance based on the table-per-hierarchy model specifies multiple types in the hierarchy by using the same database table. In this model, an explicit condition in the mapping specification identifies type in the inheritance hierarchy.

A discriminator column is included in the table to distinguish each type, and the condition references an assigned value of the column for each type. For example, the condition may specify that the value of the EntityType column is equal to P for the Person type or C for the Customer type.

The following mapping example shows the conditional mapping of the Customer and Person types.

<?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>

Table-per-Type Model

In inheritance based on the table-per-type model, the base type or ancestor type is stored in one table but additional tables are used for derived types. Fields specific to the derived types only occur in the tables that represent derived types. Mapping for the entities in this model of inheritance spans several physical tables. The presence or absence of a row in a table distinguishes types in the hierarchy. The same key value is assigned to the key property in all the tables.

The BaseType attribute of EntityType can be used in conceptual and storage schemas to indicate inheritance from the base type. The IsTypeOf<T> indicator in the mapping specification can be used to specify the base type and eliminate duplicate mapping syntax.

The following mapping example shows two separate mappings for the Customer and Person types. The TypeName attributes of the EntityTypeMapping elements distinguish the Person and Customer types. There is a table for each type. The Customer entity type and table contain the NumYears property and column that is not included in the base type.

<?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>

See Also

Tasks

How to: Define a Model with Table-per-Type Inheritance (Entity Framework)
How to: Define a Model with Table-per-Hierarchy Inheritance (Entity Framework)

Concepts

Entity Data Model Types
Helper Methods (EDM)
Entity Data Model Inheritance (Application Scenarios)