【问题标题】:Entity Framework Add Discriminator Column for Only One Child Model实体框架仅为一个子模型添加鉴别器列
【发布时间】:2017-07-20 16:40:18
【问题描述】:

我有一个抽象的父模型,因此不能创建它的实例,目前我有一个继承自它的子类。例如,我有这样的事情:

public abstract class Parent {
     public virtual int Id { get; set; }
}

public class Child1 : Parent {
     public override int Id { get; set; }
     public string SomeAttribute1 { get; set; }
     public string SomeAttribute2 { get; set; }
}

我正在使用实体框架来填充我的数据库模型,当我添加时

public virtual IDbSet<Child1> Child1 { get; set; } 根据我的上下文,我得到了下表,其中包含以下列:

家长:

  • 身份证
  • SomeAttribute1
  • SomeAttribute2

这是我所期望的。但是我遇到的问题是,我很可能稍后会向这个父类添加更多的子模型,例如另一个类,例如:

public class Child2 : Parent {
     public override int Id { get; set; }
     public string Child2Attribute1 { get; set; }
     public string Child2Attribute2 { get; set; }
}

当我将此子模型添加到上下文中时,我的 Parent 列会变成这样:

家长:

  • 身份证
  • SomeAttribute1
  • SomeAttribute2
  • Child2Attribute1
  • Child2Attribute2
  • 鉴别器

我了解鉴别器的概念,但是我的问题是在添加 Child2 类之前我的数据库中已经存在的所有 Child1 对象将没有鉴别器列,然后将具有空值.

我想这些空的鉴别器值会在以后尝试访问它们时引起问题,所以我的问题是,有没有办法在只有 1 个子实体的模型上强制使用鉴别器列?

或者有没有更好的方法来抢先处理/准备以后添加更多的子类?

或者有没有让这两个子类成为他们自己的表的好方法?我从来没有用实体框架做过很多花哨的 OOP,所以我不确定他们处理这个问题的最佳方法是什么。

感谢您的帮助!

编辑

我研究了 3 种不同的继承模型:TPH、TPT 和 TPC。 TPH 不是适用于我的场景的模型,但是 TPT 和 TPC 都可以工作。正如我在答案中提到的那样,我让 TPT 正常工作,但是 TPC 非常适合我的用例,因为我不一定想要/不需要将父类存储在数据库中(但仍然希望在我的上下文中使用它)。我设法让 TPC 几乎可以对我的代码进行以下更改:

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    modelBuilder.Entity<Child1>().Map(m =>
    {
        m.MapInheritedProperties();
        m.ToTable("Child1");
    });

    modelBuilder.Entity<Child2>().Map(m =>
    {
        m.MapInheritedProperties();
        m.ToTable("Child2");
    });
}

并将我的父模型更改为:

public abstract class Parent {
    [DatabaseGenerated(DatabaseGenerationOption.Identity)]
    public virtual int Id { get; set; }
}

但是那么我看到的问题是在孩子中填充的 Id 不是唯一的(即 Child1Child2 的 Id = 1,但这意味着存在然后是 2 个 ID = 1 的 Parent 对象,这违反了唯一键约束。

有没有一种方法可以强制自动生成的 ID 在孩子之间是唯一的?

【问题讨论】:

  • Table-Per-Type 将为您提供 2 个单独的表格。只需为两个类指定表名(通过 Attribute 或通过 fluent API)。
  • 但在我的上下文中仍会喜欢它 -- 为什么?如果您倾向于 TPC,我也会认真考虑让 EF 不了解基类并独立映射每个子类型。

标签: c# entity-framework oop discriminator


【解决方案1】:

感谢Bradley Uffner 的建议,我找到了解决问题的方法:

Table-Per-Type 做到了这一点,只需将父类添加到上下文中,然后为每个添加的子类创建单独的表,如下所示:

public virtual IDbSet<Parent> Parents { get; set; }

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
     modelBuilder.Entity<Child1>().ToTable("Child1");
     modelBuilder.Entity<Child2>().ToTable("Child2");
}

【讨论】:

  • TPT 有其自身的缺点,您必须仔细考虑 TPH/TPT/TPC 的优缺点,然后再决定哪个更适合您的场景。
  • 感谢您指出这一点。我已经查看了 TPH,这不是我想要的,但是 TPC 似乎正是我想要的结构,但是当我遵循这个 weblogs.asp.net/manavi/… 策略时,实体框架实际上不会填充子表的 id
猜你喜欢
  • 1970-01-01
  • 2015-03-25
  • 1970-01-01
  • 2013-12-04
  • 1970-01-01
  • 1970-01-01
  • 2012-07-22
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多