实体框架TPC的多重继承



我试图使用TPC风格的实体框架映射一些类,但得到了以下错误:

错误:类型"A"无法按定义映射,因为它映射从使用实体拆分或其他类型继承的属性继承形式。请选择其他继承映射策略,以便不映射继承的属性,或更改中的所有类型映射继承属性而不使用拆分的层次结构。

当我使用以下类时会发生此错误:

public abstract class BaseEntityTest
public abstract class BaseEntityTest2 : BaseEntityTest
public abstract class BaseEntityTest3 : BaseEntityTest2
public class A: BaseEntityTest3 // this class is the only one with a table in the db

在OnModelCreating方法中,我添加了以下代码来获得TPC映射

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

当我从结构中排除BaseEntityTest2时(这样A只继承BaseEntityTest而不是BaseEntityTest1),错误就会消失。这是否意味着不可能创建这个映射,或者我只是错过了什么?

编辑:

类别属性:

public abstract class BaseEntityTest
{
[Key]
public Guid Id { get; set; }
public String Info { get; set; }
[Required]
public DateTime CreationDate { get; set; }
[Required]
public String CreationUser { get; set; }
[Required]
public DateTime ModificationDate { get; set; }
[Required]
public String ModificationUser { get; set; }
[ConcurrencyCheck]
[Required]
public int LockVersion { get; internal set; }
}
public abstract class BaseEntityTest2 : BaseEntityTest
{
[Required]
public string Name { get; set; }
public string Description { get; set; }
}
public abstract class BaseEntityTest3: BaseEntityTest2 
{
[Required]
public DateTime FromDate { get; set; }
public DateTime ThruDate { get; set; }
}
public class A: BaseEntityTest3{
public String Test { get; set; }
}

该错误发生在EF 4.3.1和早期版本中,但不发生在EF 4.4和EF 5.0中。(EF 4.4实际上是EF 5.0,但以.NET 4.0作为目标平台。)

但是:只有当你在模型中使用抽象类作为实体时,才会出现错误,这意味着

  • 在上下文类中为它们设置DbSet,如

    public DbSet<BaseEntityTestX> BaseEntityTestXs { get; set; }
    
  • 或者你有一些BaseEntityTestX的Fluent映射,一些modelBuilder.Entity<BaseEntityTestX>()...的东西

  • 或者您正在使用BaseEntityTestX中的一个作为另一个(具体)实体类型中的导航属性

你需要这些吗?

只有当您真的想查询其中一个抽象实体时,在上下文中使用DbSet<BaseEntityTestX>才有意义,比如:

List<BaseEntityTest> list = context.BaseEntityTests
.Where(b => b.Info == "abc").ToList();

结果当然是继承自BaseEntityTest的具体实体的列表,但它可以是不同类型的混合,比如一些A和一些B。您需要这样的查询吗?还是只想查询一些具体的对象:

List<A> list = context.As
.Where(b => b.Info == "abc").ToList();

在后一种情况下,抽象基类不需要DbSet,也不需要任何继承映射。您只需从上下文类中删除DbSet<BaseEntityTestX>并删除TPC映射,错误就会消失。

最后一点是,在TPC映射中,对另一个实体中的一个抽象实体具有导航属性是没有意义的。它无法映射到关系数据库,因为在TPC映射中,抽象实体没有表,因此外键关系无法从具有导航属性的具体类的表中引用目标。

如果您将TPC映射扩展到基类,错误也将消失:

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

但它会为那些对我来说似乎没有意义的抽象实体创建表

在EF6.0中,时发生

EntityTypeConfiguration'<'YourBaseClass'>'

没有详细说明ALL您的派生类

this.Map<DerivedClass1>(m =>
{
m.MapInheritedProperties();
m.ToTable("..");
});

如果程序集中只有一个dervied类没有这样配置你得到这个例外

最新更新