【问题标题】:EF 5 Mixed Inheritance Types with Multi Layer Inheritance具有多层继承的 EF 5 混合继承类型
【发布时间】:2013-08-04 23:23:54
【问题描述】:

我在使用实体框架将现有数据库映射到代码库时遇到问题。我似乎也找不到任何类似的代码。我需要有多层继承,我需要层使用两种不同的映射类型。我有一些奇怪的行为。为了重现该行为,我创建了一个简单的模型并允许 EF 以它希望的方式对其进行映射。

我的实体如下:

public abstract class Root
{
    public int RootId { get; set; }

    public string RootProperty { get; set; }
}

public abstract class ChildA : Root
{
    public string ChildAProperty { get; set; }
}

public class ChildB : Root
{
    public string ChildBProperty { get; set; }
}

public class SubChildAa : ChildA
{
    public string SubChildAaProperty { get; set; }
}

public class SubChildAb : ChildA
{
    public string SubChildAbProperty { get; set; }
}

这会产生以下架构:

我的上下文如下:

class MyContext : DbContext
{
    public DbSet<SubChildAa> ChildAas { get; set; }
    public DbSet<SubChildAb> ChildAbs { get; set; }
    public DbSet<ChildB> ChildBs { get; set; }

    public MyContext()
    {
        //Database.SetInitializer<MyContext>(null);
    }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {

        modelBuilder.Entity<Root>().ToTable("Root");

        modelBuilder.Entity<ChildB>().ToTable("ChildB");

        modelBuilder.Entity<ChildA>().ToTable("ChildA");
        modelBuilder.Entity<ChildA>().Map<SubChildAa>(u => u.Requires("ChildAType").HasValue("SubChildAa"));
        modelBuilder.Entity<ChildA>().Map<SubChildAb>(u => u.Requires("ChildAType").HasValue("SubChildAb"));
        //base.OnModelCreating(modelBuilder);
    }


}

我正在尝试将 TPT 用于 Root 到 Child(A 或 B)的映射,并将 TPH 用于 ChildA 到 SubChild。主要问题是 EF 将鉴别器放在 Root 对象上。它还将 ChildA 属性放在那里,我认为这是不正确的,但现在问题不大。由于鉴别器位于根上,它会导致错误,因为 ChildB 未映射到该鉴别器中的类型。

有人可以建议一种方法,让 ChildA 表实际上保持其自己的属性和鉴别器,而不会将它们推到根表。

【问题讨论】:

    标签: c# entity-framework hierarchy


    【解决方案1】:

    类似的东西

    public abstract class Root
    {
      [Key]
      public int RootId { get; set; }
      public string RootProperty { get; set; }
    }
    
    public class ChildA : Root
    {
     [Required]
     int RootId 
     ForeignKey["RootId"]
     public Root Root {get;set;}    
     public string ChildAProperty { get; set; }
    } 
    
    public class ChildB : Root {
       [Required]
       int RootId   
       ForeignKey["RootId"]
       public Root Root {get;set;}      
       public string ChildBProperty { get; set; }
     }
    
    public class SubChildAa : ChildA
    {
      public string SubChildAaProperty { get; set; }
    }
    
    public class SubChildAb : ChildA
    {
      public string SubChildAbProperty { get; set; }
    }
    

    在您的上下文中,您希望 ChildA 和 ChildB 的 TPT

    所以

      public DbSet<ChildA> ChildAas { get; set; }
    
      public DbSet<ChildB> ChildBs { get; set; }
    

    子孩子的 TPH

      public DbSet<SubChild> Childs { get; set; }
    

    【讨论】:

    • 为什么要从 Root 继承并在 ChildA 和 B 中公开 Root 类型的属性?我从 DbSet 假设您的意思是我定义的两个中的任何一个而不是新类型?我并不是真的在寻找“类似的东西”。我了解如何独立映射 TPT 和 TPH。问题在于将它们结合起来。
    • 我实现了代码,它确实产生了我想要的架构,但有一些问题。没有创建鉴别器,这很容易通过在上下文中重载 OnModelCreating 并指定鉴别器来解决。更大的问题是它使用该域模型产生的歧义。我可以创建一个 ChildA 然后创建一个 ChildB 并将 ChildA 的 Root 设置为 ChildB 并且它会爆炸(这是意料之中的)。这确实解决了 ChildA 表上有 ChildA 属性和鉴别器的问题,但就代码而言,这是一个很大的设计妥协。
    • 我从根继承,因为那是设计。然而,导航属性也需要与外键相关联,这一位在 ChildA 和 ChildB 类中完成,这就是为什么 Root 属性会重复
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2010-11-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-05-13
    • 1970-01-01
    相关资源
    最近更新 更多