【发布时间】: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 不是唯一的(即 Child1 和 Child2 的 Id = 1,但这意味着存在然后是 2 个 ID = 1 的 Parent 对象,这违反了唯一键约束。
有没有一种方法可以强制自动生成的 ID 在孩子之间是唯一的?
【问题讨论】:
-
Table-Per-Type 将为您提供 2 个单独的表格。只需为两个类指定表名(通过 Attribute 或通过 fluent API)。
-
但在我的上下文中仍会喜欢它 -- 为什么?如果您倾向于 TPC,我也会认真考虑让 EF 不了解基类并独立映射每个子类型。
标签: c# entity-framework oop discriminator