每个层次结构表的表与共享和非共享列的映射

时间:2014-11-13 03:31:41

标签: c# sql-server entity-framework entity-framework-6 table-per-hierarchy

这是this question的扩展,我现在可以在EF6中使用它。但是,当您拥有具有共享和非共享属性的子类时,似乎存在问题。

让我们说这是我的模型设置:

public abstract class Document
{
    public int Id { get; set; }
    public string NameOnDocument { get; set; }
}

public class BirthCertificate : Document
{
    public string RegistrationNumber { get; set; }
}

public class Licence : Document
{
    public string LicenceNumber { get; set; }
}

在数据库中,我希望BirthCertificate.RegistrationNumberLicence.LicenceNumber共享同一列Number。因此,我正在设置我的模型:

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    base.OnModelCreating(modelBuilder);

    // Document - base class
    modelBuilder.Entity<Document>().HasKey(d => d.Id);
    modelBuilder.Entity<Document>()
        .Property(d => d.Id)
        .HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
    modelBuilder.Entity<Document>()
        .Property(d => d.NameOnDocument)
        .HasColumnName("Name");

    // Birth certificate
    modelBuilder.Entity<Document>().Map<BirthCertificate>(map => 
        map.Property(c => c.RegistrationNumber).HasColumnName("Number"));

    // Licence
    modelBuilder.Entity<Document>().Map<Licence>(map => 
        map.Property(l => l.LicenceNumber).HasColumnName("Number"));
}

当我生成数据库时,它看起来都按预期工作:

DB Model

现在问题就在眼前。让我们说Licence实体也需要记录到期日;所以我按如下方式添加:

public class Licence : Document
{
    public string LicenceNumber { get; set; }
    public DateTime ExpiryDate { get; set; }
}

现在,当我重新生成数据库时,它看起来像这样:

enter image description here

更重要的是,如果我尝试插入许可证和出生证明,我会得到以下例外:

  

未处理的类型&#39; System.Data.Entity.Infrastructure.DbUpdateException&#39;发生在EntityFramework.dll

中      

附加信息:在多个位置生成跨实体或关联共享的值。检查映射是否将EntityKey拆分为多个存储生成的列。

我能理解为什么会引发异常 - 因为数据库没用。

我错过了什么?

2 个答案:

答案 0 :(得分:0)

好的,事实证明问题很容易解决,但据我所知,在任何地方都没有记录。所以希望这会帮助有同样问题的人。

看起来,关键是你必须在派生实体上映射每个属性

modelBuilder.Entity<Document>().Map<Licence>(map =>
{
    map.Property(l => l.LicenceNumber).HasColumnName("Number");
    map.Property(l => l.ExpiryDate).HasColumnName("ExpiryDate");
});

现在,我的数据库正如我所期望的那样生成,而且一切都与世界相符。

答案 1 :(得分:0)

我不确定你是通过在数据库中将2列放入1来获得更多。我认为你不会节省太多空间而且你无法询问基地Number的{​​{1}},即使两个文件都有一个。{1}}。您是否考虑过将Document字段添加到基础并在覆盖上使用数据注释 - 类似这样的内容?

Number

编辑如果所有文件都没有编号:

public abstract class Document
{
    public int Id { get; set; }
    public string NameOnDocument { get; set; }
    public virtual string Number
}

public class BirthCertificate : Document
{
    [Display(Name="Registration Number"]
    [Required]
    public override string Number { get; set; }
}

public class Licence : Document
{
    [Display(Name="Licence Number"]
    [Required]
    public override string Number { get; set; }
}