实体框架 - TPH的鉴别器问题

时间:2011-04-28 15:20:27

标签: inheritance mapping entity-framework-4.1

我在保存记录时得到Invalid column name 'Discriminator'。 (Code First,EF4.1)

我有一个我希望通过EF跟踪的实体:

public class Audit
 public virtual string p1
 public virtual string p2

我有一个专业的UserAudit,它没有添加新的虚拟属性,它只是为审计设置了基础

public class UserAudit : Audit
 public UserAudit() { p1 = someval; }

配置:

public class AuditConfiguration : EntityTypeConfiguration<Audit>
  {
    public AuditConfiguration()
    {
      ToTable("_AUDIT");
      HasKey(c => c.Id);
      Property(c => c.Id).HasColumnName("AUDIT_ID");
    }
  }

回购:

public class AuditRepository : IAuditRepository
  {
    public void LogAudit(Audit audit)
    {
      using (var db = new AuditContext())
      {
        db.Audits.Add(audit);
        db.SaveChanges();
      }
    }
  }

当我repo.LogAudit( userAudit );时,我需要做什么来告诉EF正确忽略/处理专业?

3 个答案:

答案 0 :(得分:5)

从异常消息Invalid column name 'Discriminator'我得出结论,你没有让EF 4.1创建数据库表_AUDIT,否则EF会在表中创建一个名为Discriminator的列。也许你有一个没有这样一列的现有数据库表。当EF试图保存实体时,它想要存储一个表示您要保存到鉴别器列中的具体类型的值 - 但该列不存在。因此例外。

修改

因此,您需要一个鉴别器列。您可以定义自己的自定义鉴别器列,如下所示:

public class AuditConfiguration : EntityTypeConfiguration<Audit>
{
    public AuditConfiguration()
    {
        ToTable("_AUDIT");
        HasKey(c => c.Id);
        Property(c => c.Id).HasColumnName("AUDIT_ID");

        Map<Audit>(m => m.Requires("Type").HasValue<byte>(0).IsRequired());
        Map<UserAudit>(m => m.Requires("Type").HasValue<byte>(1).IsRequired());
    }
}

这会在tinyint表中使用不可为空的Type_AUDIT,其值0用于基本Audit类型对象和值{{ 1}}用于派生的1类型对象。

答案 1 :(得分:1)

@Slauma绝对正确,你应该使用他的解决方案。我只是在解释为什么会发生这种情况。

实体中的继承必须在数据库中建模,因为当您从数据库加载实体时,EF必须知道它是否应该实现AuditUserAudit实例。默认情况下,EF使用名为Table per Hierarchy继承的东西,其中基类型和所有子类型存储在同一个表中。为了支持这种情况,EF期望默认的Discriminator调用表中的附加列。此列将用于存储不同的实例 - 默认情况下,它包含类型的名称。

答案 2 :(得分:1)

就我而言,非EF模型继承自EF模型。我已经将所有属性复制到非EF模型而不是继承,这对我来说就是解决方案。

public class ApplicationContext : DbContext
{
    public DbSet<Person> Persons { get; set; }
}

public class Person
{
    public int PersonId { get; set; }
    public string Name { get; set; }
}

<强>之前:

public class PersonWithExtraInfo:Person
{
    public string ExtraInfo { get; set; }
}

<强>后:

public class PersonWithExtraInfo
{
    public int PersonId { get; set; }
    public string Name { get; set; }
    public string ExtraInfo { get; set; }
}