Entity Configuration with multiple level inheritance

.net c# ef-fluent-api entity-framework entity-framework-6

Question

I have the following supertype/subtype pattern at the database level:

MotherTable
- MainDiscriminator
- CommonAttribute1
- CommonAttribute2

ChildTable1
    - MainDiscriminator (value: 1)
    - AdditionalAttributes...

ChildTable2
    - MainDiscriminator (value: 2)
    - AdditionalAttributes...

Until this point, pretty typical implementation configuration for mapping:

Map<ChildTable1>(m => m.Requires("MainDiscriminator").HasValue("1"));
Map<ChildTable2>(m => m.Requires("MainDiscriminator").HasValue("2"));

Now where I am having issues is configuring second level of inheritances; ChildTable2 has grand children with a different discriminator that MotherTable knows nothing about. Would look like this

ChildTable2
    - MainDiscriminator (value: 2)
    - AdditionalAttributes...
    - SecondaryDiscriminator

GrandChild1
    - SecondaryDiscriminator (value: 1)
    - AdditionalAttributes...

GrandChild2
    - SecondaryDiscriminator (value: 2)
    - AdditionalAttributes...

I tried various approaches, but I either run into misconfiguration stating that two entities are being mapped to same row or EF tries to enter a null value to a non existing column named "Discriminator" in MotherTable.

One of the avenue that seemed to allow to workaround this, was a DbInterceptor removing those unwanted "Discriminator" column inserts/updates/deletes, but I would rather not go there.

Any ideas/thoughts would be appreciated.

1
0
3/9/2018 2:20:04 AM

Popular Answer

By the time I wrote this, you might have already found the solution. Still, I did this so you may get some insight about what other options might have in the table.

I may say that your case is the right one to implement TpT (Table per Type) inheritance in EF 6.

So, this is my take for the case, starting from simple POCO classes :

public class MotherTable
{
    public int MotherId { get; set; }
    public int MainDiscriminator { get; set; }
    public string CommonAttribute1 { get; set; }
    public string CommonAttribute2 { get; set; }
}

public class ChildTable1 : MotherTable
{
    public string AdditionalAttribute1 { get; set; }
}

public class ChildTable2 : MotherTable
{
    public int SecondaryDiscriminator { get; set; }
    public string AdditionalAttribute2 { get; set; }
}

public class GrandChild1 : ChildTable2
{
    public string AdditionalAttributes21 { get; set; }
}

public class GrandChild2 : ChildTable2
{
    public string AdditionalAttributes22 { get; set; }
}

Setup in EF 6 using fluent API (code-first scenario) like this :

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    modelBuilder.Entity<MotherTable>().ToTable("MotherTable").HasKey<int>(c => c.MotherId);
    modelBuilder.Entity<ChildTable1>().ToTable("ChildTable1");
    modelBuilder.Entity<ChildTable2>().ToTable("ChildTable2");
    modelBuilder.Entity<GrandChild1>().ToTable("GrandChild1");
    modelBuilder.Entity<GrandChild2>().ToTable("GrandChild2");
}

Tested by running this snippet :

using (var context = new StackoverflowEntities())
{
    var account1 = new GrandChild1
    {
        MotherId = 1,
        MainDiscriminator = 2,
        CommonAttribute1 = "Mother common 1",
        CommonAttribute2 = "Mother common 2",
        AdditionalAttribute2 = "Child Add Attr 2",
        AdditionalAttributes21 = "Grand Child Add Attr 2.1",
        SecondaryDiscriminator = 1
    };

    var accounts1 = context.Set<GrandChild1>();
    accounts1.Add(account1);

    var account2 = new GrandChild2
    {
        MotherId = 2,
        MainDiscriminator = 2,
        CommonAttribute1 = "Mother common 1",
        CommonAttribute2 = "Mother common 2",
        AdditionalAttribute2 = "Child Add Attr 2",
        AdditionalAttributes22 = "Grand Child Add Attr 2.2",
        SecondaryDiscriminator = 2
    };

    var accounts2 = context.Set<GrandChild2>();
    accounts2.Add(account2);

    context.SaveChanges();
}

It will generate a database schema like this :

enter image description here

and will distribute the inserted data (from the snippet above), like this :

enter image description here

I hope this post can give you something to consider, even if you've fixed your codes and it's not exactly what you're looking for. Or maybe you could tell me something I don't know, if any.

1
3/14/2018 3:03:22 AM


Related Questions





Related

Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow