C# 具有多级继承的实体配置

C# 具有多级继承的实体配置,c#,.net,entity-framework,entity-framework-6,ef-fluent-api,C#,.net,Entity Framework,Entity Framework 6,Ef Fluent Api,我在数据库级别具有以下超类型/子类型模式: MotherTable - MainDiscriminator - CommonAttribute1 - CommonAttribute2 ChildTable1 - MainDiscriminator (value: 1) - AdditionalAttributes... ChildTable2 - MainDiscriminator (value: 2) - AdditionalAttributes... 到

我在数据库级别具有以下超类型/子类型模式:

MotherTable
- MainDiscriminator
- CommonAttribute1
- CommonAttribute2

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

ChildTable2
    - MainDiscriminator (value: 2)
    - AdditionalAttributes...
到目前为止,映射的典型实现配置是:

Map<ChildTable1>(m => m.Requires("MainDiscriminator").HasValue("1"));
Map<ChildTable2>(m => m.Requires("MainDiscriminator").HasValue("2"));
我尝试了各种方法,但我要么遇到错误配置,指出两个实体映射到同一行,要么EF尝试向MotherTable中不存在的名为“Discriminator”的列输入空值

解决这个问题的一个方法是使用DbInterceptor删除那些不需要的“Discriminator”列插入/更新/删除,但我不想去那里


如果您有任何想法,我们将不胜感激。

在我写这篇文章时,您可能已经找到了解决方案。不过,我这样做是为了让您了解表中可能有哪些其他选项

我可以说,您的案例是在EF6中实现TpT(每类型表)继承的正确案例

这是我对这个案例的看法,从简单的POCO类开始:

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; }
}
使用fluent API在EF 6中设置(代码优先场景),如下所示:

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");
}
模型创建时受保护的覆盖无效(DbModelBuilder modelBuilder)
{
modelBuilder.Entity().ToTable(“MotherTable”).HasKey(c=>c.MotherId);
modelBuilder.Entity().ToTable(“ChildTable1”);
modelBuilder.Entity().ToTable(“ChildTable2”);
modelBuilder.Entity().ToTable(“1”);
modelBuilder.Entity().ToTable(“2”);
}
通过运行以下代码段进行测试:

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();
}
使用(var context=new stackoverfloventies())
{
var account1=新的1
{
MotherId=1,
主鉴别器=2,
CommonAttribute1=“普通母亲1”,
CommonAttribute2=“普通母亲2”,
AdditionalAttribute2=“子添加属性2”,
AdditionalAttributes21=“孙子添加属性2.1”,
二次鉴别器=1
};
var accounts1=context.Set();
账户1.增加(账户1);
var account2=新的2
{
MotherId=2,
主鉴别器=2,
CommonAttribute1=“普通母亲1”,
CommonAttribute2=“普通母亲2”,
AdditionalAttribute2=“子添加属性2”,
AdditionalAttributes22=“孙子添加属性2.2”,
二次鉴别器=2
};
var accounts2=context.Set();
会计2.增加(会计2);
SaveChanges();
}
它将生成如下所示的数据库架构:

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");
}

并将分发插入的数据(来自上面的代码段),如下所示:

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");
}


我希望这篇文章能给你一些考虑,即使你已经修正了代码,也不是你想要的。或者你可以告诉我一些我不知道的事情,如果有的话。

奇怪。看起来您在“每层次表(TpH)”和“每类型表(TpT)”方法之间搞砸了。首先,TpH方法将通过使用鉴别器在一个表中结束,此时TpT将以一对一模式连接所有表,而不使用鉴别器。但如果我错了,请纠正我。@Erlangahastohandoko我实际上尝试了严格的三级TpT,但没有成功(即使把主鉴别器一路降下来)。在最近的一次调查中,孙子和孙女都在儿童表2中。我原以为那会更容易管理,但似乎不是。你成功了吗?对不起,我还是不明白这个问题,因为如果你坚持TpT,没有鉴别器,你仍然会得到你想要的。我以前先用代码做过,有3个继承级别。您是从现有数据库开始的吗?@erlangahastohandoko或多或少地结合了TpT+TpH,但它会创建一些非常长的查询。。。虽然你的陈述让我重新思考。。。我猜我是想用.Requires强制使用鉴别器,但对于TpT,在正确的表中插入类型才是真正重要的。在这些情况下,我将如何强制使用某个鉴别器值?将它们视为EF中的普通列如何?这对你有意义吗?