我试图将两个不同的EF模型映射到同一个表SharedTable,让我们称它们为EntityA和EntityB。我让它们都扩展了一个名为BaseEntity的基本实体。
EntityA仅使用SharedTable字段定义,EntityB在SharedTable和EntityBTable中包含字段。
modelBuilder.Entity<BaseEntity>()
.Map<EntityA>(m => m.Requires("IsEntityA").HasValue<bool>(true))
.Map<EntityB>(m => m.Requires("IsEntityA").HasValue<false>(true));
modelBuilder.Configurations.Add(new EntityBMap());
modelBuilder.Configurations.Add(new EntityAMap());
modelBuilder.Configurations.Add(new BaseEntityMap());
模型看起来像这样
public class BaseEntity
{
[Required]
public int Id { get; set; }
public int SharedTableField1 { get; set; }
}
public class EntityA : BaseEntity
{
public int SharedTableField2 { get; set; }
}
public class EntityB : BaseEntity
{
public int EntityBTableField1 { get; set; }
}
映射是
public class BaseEntityMap : EntityTypeConfiguration<BaseEntity>
{
public BaseEntityMap()
{
// Primary Key
this.HasKey(t => t.Id);
this.ToTable("SharedTable");
this.Property(t => t.Id).HasColumnName("Id");
this.Property(t => t.SharedTableField1).HasColumnName("SharedTableField1");
}
}
public class EntityAMap : EntityTypeConfiguration<EntityA>
{
public EntityAMap()
{
this.HasKey(t => t.Id);
this.Property(t => t.Id).HasColumnName("Id");
this.ToTable("SharedTable");
this.Property(t => t.SharedTableField2).HasColumnName("SharedTableField2");
}
}
public class EntityBMap : EntityTypeConfiguration<EntityB>
{
public EntityBMap()
{
Map(c =>
{
HasKey(t => t.Id);
Property(t => t.Id).HasColumnName("Id");
c.Properties(t => new
{
t.SharedTableField2
});
c.ToTable("SharedTable");
});
Map(c =>
{
c.Properties(t => new
{
t.EntityBTableField1
});
c.ToTable("EntityBTable");
});
}
}
我得到的错误说:
类型&#39; System.NotSupportedException&#39;的第一次机会异常。发生在EntityFramework.dll
中其他信息:类型&#39; EntityB&#39;无法按定义映射,因为它映射了使用实体拆分或其他形式的继承的类型的继承属性。选择不同的继承映射策略,以便不映射继承的属性,或更改层次结构中的所有类型以映射继承的属性,并且不使用拆分。
有什么方法吗?
答案 0 :(得分:0)
您选择的继承策略是Table per Type (TPT)。
您有三种类型:一种基本类型BaseEntity
和两种派生类型EntityA
和EntityB
。你决定将它们分成三个单独的表格。 BaseEntity
和EntityA
的{{1}}属性将放在一个表格中。 EntityB
和EntityA
每个都有EntityB
表中基本属性的外键。
此继承策略是否最适合您的问题,取决于您是否主要查询BaseEntity
那个......或者实体A BaseEntities
EntityB` ...考虑使用Table per concrete class (TPC)
TPT继承策略意味着每个查询/
的连接......使用基类属性。如果您使用TPC,则不需要此加入。但是,每当你要求“BaseEntities”时,TPC都需要一个Concat ...所以这取决于你最常做什么样的查询,哪种继承策略最适合你的需要。
如果你想坚持战略TPT,似乎你没有正确地建立你的模型。
EntityA
个对象。如果你允许这样做,它就不会是继承,而是一对一或零关系:每个BaseEntity
属于一个EntityA
,每个{{1} }}有一个或一个'EntityA BaseEntity
BaseEntity BaseEntity
EntityA . This is not what you want: every
EntityB has exactly either one
/ or one '
只有一个&#39; BaseEntity` < / LI>
, and every 'EntityA
个对象,因此BaseEntity`类应该被声明为抽象,就像TPT的给定链接一样。 EntityB
en BaseEntity
的类定义中,请勿提及EntityA
表的外键。再次,请参阅TPT的给定链接我认为抽象基类和缺少外键是 让实体框架知道您选择的关键信息 继承战略TPT。
当我像这样构建你的模型时,实体框架创建了像TPT这样的三个表。任何额外的流畅API和属性都是必需的。即使我没有提到外键,实体框架也知道它们需要作为多态关联。再次看到TPT的链接
顺便问一下,整数上的[Required]是否有用?即使我想,我也不能给这个整数一个空值。你不是指[Key]吗?正如您所追随的那样entity framework code first conventions即使这是不必要的。