Table-每个层次结构和复合主键

Table-per-hierarchy and composite primary key

我在遗留数据库(我无法修改)中有两个 table,数据如下:

Table1 有一个复合主键(Code, Abbrev),但 Abbrev 也用作鉴别符(见下文)。 Table2 有两个外键列(CodeA、CodeB),它们都引用 Table1 中的同一个字段 Code。 Table1.Code 字段中有重复项。

我想对 Entity framework 6 使用 table-per-hierarchy 方法。因此,我创建了以下模型 classes:

[Table("Table1")]
public class MyBaseClass
{
    [Key]
    public string Code { get; set; }
}

public class MyBaseClassA : MyBaseClass
{
}

public class MyBaseClassB: MyBaseClass
{
}

[Table("Table2")]
public class SubClass
{
    [Key]
    public int Id { get; set; }

    [Required]
    [ForeignKey("MyBaseClassA")]
    public string CodeA { get; set; }

    public virtual MyBaseClassA ClassA { get; set; }

    [Required]
    [ForeignKey("MyBaseClassB")]
    public string CodeA { get; set; }

    public virtual MyBaseClassB ClassB { get; set; }

}

我在我的 DataContext 中定义了 table-per-hierarchy:DbContext class 如下:

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Entity<MyBaseClass>().Map<MyBaseClassA>(m => m.Requires("Abbrev").HasValue("A"))
            .Map<MyBaseClassB>(m => m.Requires("Abbrev").HasValue("B"));
    }

问题是当我想使用这种映射时 - 我不能将鉴别器字段 (Table1.Abbrev) 用作 MyBaseClass 中复合键的一部分 - 我收到以下错误:

All objects in the EntitySet 'DataContext.MyBaseClass' must have unique primary keys. However, an instance of type 'MyBaseClassA' and an instance of type 'MyBaseClassB' both have the same primary key value, 'EntitySet=MyBaseClass;Code=1'.

是否可以将上面的模型映射到 Entity framework 6(或更新版本)?

创建一个新的 table,将 "Abbrev" 列作为其主键。 (这个 table 根据你的例子只有两行, "Abbrev" 列值为 "A" 和 "B"。)然后定义这个新的 [=20= 之间的外键关系] 和现有的 Table1。在代码中,通过附加 "Abbrev" 列作为现有主键定义的一部分来更新 Table1 的 MyBaseClass。

这应该可以解决 MyBaseClass 生成的 "must have unique primary keys" 错误。

恐怕 Entity Framework 无法做到这一点。

首先,您必须映射 Table1 的完整键,因为 EF 不可能仅通过 Code 识别 Table1 对象。不支持作为复合主键一部分的鉴别器。

所以你不能子类型Table1。如果仅此而已,您可以选择不使用继承。但是 Table2 才是真正的阻尼器。 EF 需要外键来引用 full 主键。所以,由于 Table1 应该有一个复合键,Table2 的两个外键也应该看起来像 { Code, Abbrev }。好吧,Table2.

中甚至没有一个 Abbrev 字段

您唯一可以做的就是按原样映射 Table1(没有继承),并且 Table2 之间没有任何关联。您必须手动编写(某种)连接才能在一个查询中从数据库中获取相关记录。

例如,要获得 Table2Table1 作为 A

from t1 in context.Table1s
join t2 in context.Table2s on t1.Code equals t2.CodeA
where t1.Abbrev == "A"
select new { A = t1, t2 }

Table2 同时具有 Table1 作为 ATable1 作为 B:

from t2 in context.Table2s
select new 
{
    t2,
    A = (from t1 in context.Table1s 
         where t1.Code == t2.CodeA && t1.Abbrev == "A")
        .FirstOrDefault(),
    B = (from t1 in context.Table1s 
         where t1.Code == t2.CodeB && t1.Abbrev == "B")
        .FirstOrDefault(),
}