C# 带表拆分的EF继承
我试图将两个不同的EF模型映射到同一个表SharedTable,让我们称它们为EntityA和EntityB。我让它们都扩展了一个名为BaseEntity的基本实体 EntityA仅使用SharedTable字段定义,EntityB在SharedTable和EntityBTable中有字段C# 带表拆分的EF继承,c#,entity-framework,C#,Entity Framework,我试图将两个不同的EF模型映射到同一个表SharedTable,让我们称它们为EntityA和EntityB。我让它们都扩展了一个名为BaseEntity的基本实体 EntityA仅使用SharedTable字段定义,EntityB在SharedTable和EntityBTable中有字段 modelBuilder.Entity<BaseEntity>() .Map<EntityA>(m => m.Requires("IsEn
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 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");
});
}
}
公共类BaseEntityMap:EntityTypeConfiguration
{
公共BaseEntityMap()
{
//主键
this.HasKey(t=>t.Id);
本表为ToTable(“SharedTable”);
this.Property(t=>t.Id).HasColumnName(“Id”);
this.Property(t=>t.SharedTableField1).HasColumnName(“SharedTableField1”);
}
}
公共类EntityAMap:EntityTypeConfiguration
{
公共实体映射()
{
this.HasKey(t=>t.Id);
this.Property(t=>t.Id).HasColumnName(“Id”);
本表为ToTable(“SharedTable”);
this.Property(t=>t.SharedTableField2).HasColumnName(“SharedTableField2”);
}
}
公共类EntityBMap:EntityTypeConfiguration
{
公共实体bmap()
{
地图(c=>
{
HasKey(t=>t.Id);
属性(t=>t.Id);
c、 属性(t=>new
{
t、 SharedTableField2
});
c、 ToTable(“SharedTable”);
});
地图(c=>
{
c、 属性(t=>new
{
t、 EntityBTableField1
});
c、 ToTable(“实体表”);
});
}
}
我得到的错误是:
EntityFramework.dll中首次出现类型为“System.NotSupportedException”的异常
其他信息:无法按定义映射类型“EntityB”,因为它映射使用实体拆分或其他继承形式的类型的继承属性。选择不同的继承映射策略以不映射继承的属性,或者将层次结构中的所有类型更改为映射继承的属性而不使用拆分
有没有办法解决这个问题?您选择的继承策略是 您有三种类型:一种基本类型
BaseEntity
和两种派生类型EntityA
和EntityB
。你决定把它们放在三张不同的桌子上。EntityA
和EntityB
的BaseEntity
属性将放在一个表中EntityA
和EntityB
在BaseEntity
表中都有其基本属性的外键
这种继承策略是否最适合您的问题取决于您主要是查询“BaseEntities that…”还是查询“EntityA that…”和“Entityb that…”
是不是使用更适合您的问题
如果您选择TPT继承策略,那么对于每个查询,“EntityA with some base class properties that…”将需要一个联接
如果您使用TPC,则不需要此连接。然而,TPC的缺点是,每当您请求“BaseEntities that…”时,两个表之间就需要Concat
因此,这取决于您最常执行的查询类型,哪种继承策略最适合您的需要
如果您想坚持战略TPT,那么您似乎没有正确构建模型
- 您不希望任何人单独存储
对象。如果允许的话,它不是继承,而是一对零或一个关系:每个BaseEntity
都属于一个EntityA
,每个BaseEntity
都有零或一个“EntityABaseEntity
BaseEntity。这不是您想要的:每个
EntityA都有一个
EntityB或一个'
/,而每个'EntityA
都有一个'BaseEntity'`EntityB
- 由于您不想在没有派生类的情况下存储
对象,因此应该将“BaseEntity”类声明为抽象类,如给定的TPT链接中所示李>BaseEntity
- 在
enEntityA
的类定义中,不要提及EntityB
表的外键。同样,请参见TPT的给定链接BaseEntity
- 在模型构建中,仅提及表名,必要时提及列名。别提外键
顺便问一下,整数上的[Required]有用吗?即使我想,我也不能给这个整数一个空值。你不是指[钥匙]吗?因为您遵循的是偶数,所以这是不必要的。为什么要将
t.EntityBTableField1
映射到另一个表?(这被称为实体拆分)。将其存储在另一个表中是有意义的,因为它不会在所有记录中使用,因此减少了不需要提取的数据量。如果实际上是关于大型对象或昂贵的计算字段,这可能是有意义的。我不会担心一些int
s或其他小类型。您还可以使用投影(Select(x=>new{…}
)来限制查询结果中的字段数量。感谢Gert,这是我为提问而创建的一个简化场景,但是需要移动的真实数据非常大
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");
});
}
}