Search code examples
entity-frameworkentity-framework-4table-per-hierarchytable-per-type

EF: Can I mix TPH and TPT when abstract base and a few concrete types are in TPH-table and other types have their own table?


First of all, these questions are similar but definitely not the same:

Can I mix Table per Hierarchy and Table per Type in Entity Framework? - Refers to a different scenario.

Entity Framework: mix table per type and table per hierarchy - Yet another scenario, that despite accepting answer to first scenario is not related to it (*).

(*) Second of all, I have sucessfully mixed table-per-type and table-per-hierarchy in Entity Framework, when base entity is mapped using table-per-entity and the table with the discriminator of the table-per-hierarchy is lower down the chain.


I am trying to map the following:

Tables:

BaseTable
{
    int PK1;
    int PK2;
    string? Value1;
    double? Value2;
}

ChildTable3
{
    int PK1;
    int PK2;
    int Value;
}

Entities:

abstract BaseEntity : class // Maps to BaseTable
{
    int PK1; // Maps to PK1 in relevant table
    int PK2; // Maps to PK2 in relevant table
}

Entity1 : BaseEntity // Maps to BaseTable when Value1 != null
{
    string Value; // Maps to Value1
}

Entity2 : BaseEntity // Maps to BaseTable when Value1 == null && Value2 != null
{
    double Value; // Maps to value2
}

Entity3 : BaseEntity // Maps to ChildTable3
{
    int Value; // Maps to value
}

Prior to adding Entity3 mappings worked.

After adding Entity3 and its mapping, I receive the following error while compiling:

Error 1 Error 3026: Problem in mapping fragments starting at lines 980, 986, 995:Data loss or key constraint violation is possible in table BaseTable. An Entity with Key (PK) will not round-trip when: (PK is in 'BaseTables' EntitySet AND Entity is type [MyNamespace.Entity3]) Path\To\My.edmx 981 15 MyAssembly

  • Is there a way to make this work?
  • If it is possible to hack the edmx to make this work, will I loose the hack on every update from database?

Solution

  • I found a workflow that enables performing such mappings via designer:

    1. Create BaseEntity, Entity1, Entity2, Entity3
    2. Map BaseEntity to BaseTable as abstract
    3. Map Entity1 to BaseTable with condition
    4. Map Entity2 to BaseTable with conditions
    5. Map Entity3 to ChildTable3
    6. Unmap BaseEntity

    To add additional child tables later on:

    1. Remap BaseEntity
    2. Map new child tables
    3. Unmap BaseEntity