要使用每个具体类型的表,请使用MapInheritedProperties 告诉 EF 基类属性是子类表的一部分。
对于 EntityTypeConfiguration 设置:
public class MyEntityConfiguration : EntityTypeConfiguration<MyEntity>
{
public MyEntityConfiguration()
{
Map(x => x.MapInheritedProperties());
ToTable("MyEntities");
}
}
如果您使用模型构建器来设置实体,那么:
modelBuilder.Entity<MyEntity>().Map(m =>
{
m.MapInheritedProperties();
m.ToTable("MyEntities");
}
在下方编辑
(也编辑了上面的示例,MapInheritiedProperties 必须在 ToTable 之前)
如果您想要基类级别的子关系,那么您应该将数据模型构建为按层次结构的表,而不是按具体的表,因为表之间的 FK 关系是一对一的。 ModuleHistory 不能有指向“FirstEntity”或“SecondEntity”的 FK。
可以让 EF 对此进行映射,但我不确定是否要使用 Code-First 进行尝试。使用实体配置:
给定原始示例中的类结构:
public class FirstEntityConfiguration : EntityTypeConfiguration<FirstEntity>
{
public FirstEntityConfiguration()
{
Map(x => x.MapInheritedProperties());
ToTable("FirstEntity");
HasKey(x => x.Id);
HasMany(x => x.History)
.WithOptional(x => (FirstEntity)x.Module)
.Map(x => x.MapKey("ModuleId"));
}
}
public class SecondEntityConfiguration : SecondEntityConfiguration<SecondEntity>
{
public SecondEntityConfiguration()
{
Map(x => x.MapInheritedProperties());
ToTable("SecondEntity");
HasKey(x => x.Id);
HasMany(x => x.History)
.WithOptional(x => (SecondEntity)x.Parent)
.Map(x => x.MapKey("ModuleId"));
}
}
public class ModuleHistoryConfiguration : EntityTypeConfiguration<ModuleHistory>
{
public ModuleHistoryConfiguration()
{
ToTable("ModuleHistory");
HasKey(x => x.Id);
}
}
// This mapping is needed because ModuleHistory's reference to BaseEntity. EF needs to know there is a Key.
public class BaseEntityConfiguration : EntityTypeConfiguration<BaseEntity>
{
public BaseEntityConfiguration()
{
HasKey(x => x.Id);
}
}
然后,当您获取 FirstEntity 或 SecondEntity 时,您将收到任何历史记录。
这个实现有几个严重的警告:
- 您失去了对 Module History 的 FK 约束,因此数据库不会为孤立(无级联删除)或历史与父级之间的正确关联提供任何保护。
- 您必须对 TpCC 表上的 PK 负责,以避免在 FirstEntity 和 SecondEntity 之间重复密钥的可能性。此处的选项包括表之间的共享序列,或使用 UniqueIdentifier (/w NewSequentialId())
最终,如果您希望基类中的子引用,您可能会更好地使用按层次结构表配置,否则将历史记录分为两个类并将关系移至实现类。