3

我在旧数据库中有两个表(我无法修改),数据如下:

两个旧表

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

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

[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 : DbContext 类中定义了 table-per-hierarchy ,如下所示:

    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 中复合键的一部分 - 我收到以下错误:

EntitySet 'DataContext.MyBaseClass' 中的所有对象都必须具有唯一的主键。但是,“MyBaseClassA”类型的实例和“MyBaseClassB”类型的实例都具有相同的主键值,“EntitySet=MyBaseClass;Code=1”。

是否可以将上面的模型与实体框架 6(或更高版本)映射?

4

2 回答 2

1

恐怕实体框架无法做到这一点。

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

所以你不能 subtype Table1。现在,如果仅此而已,您可以选择不使用继承。而是Table2真正的阻尼器。EF 要求外键引用完整的主键。所以,既然Table1应该有一个复合键,那么Table2的两个外键也应该是这样的{ Code, Abbrev }。好吧,AbbrevTable2.

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

例如,要获得 aTable2Table1as 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 }

或者 aTable2同时具有 a Table1asA和 a Table1as 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(),
}
于 2015-02-12T20:49:24.443 回答
0

创建一个以“Abbrev”列作为主键的新表。(该表在您的示例中只有两行,“Abbrev”列值为“A”和“B”。)然后定义这个新表和现有 Table1 之间的外键关系。在代码中,通过将“Abbrev”列附加为现有主键定义的一部分来更新 Table1 的 MyBaseClass。

这应该可以解决 MyBaseClass 生成的“必须具有唯一的主键”错误。

于 2015-02-12T18:16:51.467 回答