Search code examples
entity-frameworktable-per-hierarchy

Entity Framework TPH with multiple abstract inheritance


I'm trying to do a Table Per Hierarchy model in Entity Framework(VS 2008 sp1, 3.5).

Most of my models have been very simple, an abstract type with multiple sub-types that inherit from it.

However, I've been struggling with this latest challenge. I have STUDENTS that I'd like to inherit from PERSONS(abstract) that should inherity from PARTIES(abstract).

Every time I do this I get a "Error 2078: The EntityType 'Model.PERSONS' is Abstract and can be mapped only using IsTypeOf." I guess the problem is PARTIES is already defined as IsTypeOf in the entity set.

So is this even possible? I can work around it by making PERSONS abstract = false and assigning a bogus conditional mapping. But this seems like a silly workaround.


Solution

  • Edit the model using XML Editor: find the mapping and add IsTypeOf to the corresponding EntityTypeMapping tag.
    Here is an example resembling your case:
    SQL Server DDL:

    CREATE TABLE [dbo].[Student] (
        [Id] [int] IDENTITY(1,1) NOT NULL,
        [PartyInfo] [varchar](max) NOT NULL,
        [PersonInfo] [varchar](max) NOT NULL,
        [StudInfo] [varchar](max) NOT NULL,
        CONSTRAINT [PK_Student] PRIMARY KEY CLUSTERED (  [Id] ASC  )
      )

    EDMX:

    <?xml version="1.0" encoding="utf-8"?>
    <edmx:Edmx Version="1.0" 
    xmlns:edmx="http://schemas.microsoft.com/ado/2007/06/edmx">
    <!-- EF Runtime content -->
    <edmx:Runtime>
    <!-- SSDL content -->
    <edmx:StorageModels>
      <Schema Namespace="test_1Model.Store" Alias="Self" 
    Provider="System.Data.SqlClient" ProviderManifestToken="2005" 
    xmlns:store="http://schemas.microsoft.com/ado/2007/12/edm/EntityStoreSchemaGenerator" 
    xmlns="http://schemas.microsoft.com/ado/2006/04/edm/ssdl">
        <EntityContainer Name="test_1ModelStoreContainer">
          <EntitySet Name="Student" EntityType="test_1Model.Store.Student" 
    store:Type="Tables" Schema="dbo" />
        </EntityContainer>
        <EntityType Name="Student">
          <Key>
            <PropertyRef Name="Id" />
          </Key>
          <Property Name="Id" Type="int" Nullable="false" 
    StoreGeneratedPattern="Identity" />
          <Property Name="PartyInfo" Type="varchar(max)" Nullable="false" />
          <Property Name="PersonInfo" Type="varchar(max)" Nullable="false" />
          <Property Name="StudInfo" Type="varchar(max)" Nullable="false" />
        </EntityType>
      </Schema>
    </edmx:StorageModels>
    <!-- CSDL content -->
    <edmx:ConceptualModels>
      <Schema Namespace="test_1Model" Alias="Self" 
    xmlns="http://schemas.microsoft.com/ado/2006/04/edm">
        <EntityContainer Name="test_Entities">
          <EntitySet Name="PartySet" EntityType="test_1Model.Party" />
        </EntityContainer>
        <EntityType Name="Party" Abstract="true">
          <Key>
            <PropertyRef Name="Id" />
          </Key>
          <Property Name="Id" Type="Int32" Nullable="false" />
          <Property Name="PartyInfo" Type="String" Nullable="false" 
    MaxLength="Max" Unicode="false" FixedLength="false" />
        </EntityType>
        <EntityType Name="Person" BaseType="test_1Model.Party" Abstract="true" >
          <Property Name="PersonInfo" Type="String" Nullable="false" />
        </EntityType>
        <EntityType Name="Student" BaseType="test_1Model.Person" >
          <Property Name="StudInfo" Type="String" Nullable="false" />
        </EntityType>
      </Schema>
    </edmx:ConceptualModels>
    <!-- C-S mapping content -->
    <edmx:Mappings>
      <Mapping Space="C-S" 
    xmlns="urn:schemas-microsoft-com:windows:storage:mapping:CS">
        <EntityContainerMapping 
    StorageEntityContainer="test_1ModelStoreContainer" 
    CdmEntityContainer="test_Entities">
          <EntitySetMapping Name="PartySet">
            <EntityTypeMapping TypeName="IsTypeOf(test_1Model.Party)">
              <MappingFragment StoreEntitySet="Student">
                <ScalarProperty Name="PartyInfo" ColumnName="PartyInfo" />
                <ScalarProperty Name="Id" ColumnName="Id" />
              </MappingFragment>
            </EntityTypeMapping>
            <EntityTypeMapping TypeName="IsTypeOf(test_1Model.Person)">
              <MappingFragment StoreEntitySet="Student">
                <ScalarProperty Name="Id" ColumnName="Id" />
                <ScalarProperty Name="PersonInfo" ColumnName="PersonInfo" />
              </MappingFragment>
            </EntityTypeMapping>
            <EntityTypeMapping TypeName="test_1Model.Student">
              <MappingFragment StoreEntitySet="Student">
                <ScalarProperty Name="PartyInfo" ColumnName="PartyInfo" />
                <ScalarProperty Name="PersonInfo" ColumnName="PersonInfo" />
                <ScalarProperty Name="Id" ColumnName="Id" />
                <ScalarProperty Name="StudInfo" ColumnName="StudInfo" />
              </MappingFragment>
            </EntityTypeMapping>
         </EntitySetMapping>
      </EntityContainerMapping>
    </Mapping>
    </edmx:Mappings>
    </edmx:Runtime>
    <!-- EF Designer content (DO NOT EDIT MANUALLY BELOW HERE) -->
    <edmx:Designer xmlns="http://schemas.microsoft.com/ado/2007/06/edmx">
        <edmx:Connection>
          <DesignerInfoPropertySet>
            <DesignerProperty Name="MetadataArtifactProcessing" 
    Value="EmbedInOutputAssembly" />
          </DesignerInfoPropertySet>
        </edmx:Connection>
      <edmx:Options>
        <DesignerInfoPropertySet>
          <DesignerProperty Name="ValidateOnBuild" Value="true" />
        </DesignerInfoPropertySet>
      </edmx:Options>
      <!-- Diagram content (shape and connector positions) -->
      <edmx:Diagrams>
        <Diagram Name="SqlServer_Model" />
      </edmx:Diagrams>
    </edmx:Designer>
    </edmx:Edmx>