我在遗留数据库中有两个表(我无法修改),数据如下:
Table1具有复合主键(Code,Abbrev),但Abbrev也用作鉴别器(见下文)。 Table2有两个外键列(CodeA,CodeB),它们都引用Table1中的相同字段代码。 Table1.Code字段中有重复项。
我想在Entity框架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”。
是否可以使用Entity framework 6(或更新版本)映射上面的模型?
答案 0 :(得分:1)
我担心实体框架无法做到这一点。
首先,您必须映射Table1
的完整密钥,因为EF只能通过Table1
识别Code
个对象。并且不支持作为复合主键一部分的鉴别器。
因此您无法预设Table1
子类型。现在,如果这就是全部,您可以选择不使用继承。但是Table2
才是真正的阻尼者。 EF需要外键才能引用完整主键。因此,由于Table1
应该有一个复合键,Table2
两个foreigns键也应该看起来像{ Code, Abbrev }
。好吧,Abbrev
中甚至没有一个Table2
字段。
你唯一能做的就是按原样映射Table1
(没有继承),并且Table2
之间没有任何关联。您必须手动编写连接(排序)以在一个查询中从数据库中获取相关记录。
例如,要获得Table2
Table1
作为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
为A
而Table1
为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(),
}
答案 1 :(得分:0)
创建一个以“Abbrev”列为主键的新表。 (此表每个示例只有两行,“Abbrev”列值为“A”和“B”。)然后在此新表和现有Table1之间定义外键关系。在代码中,通过附加“Abbrev”列作为现有主键定义的一部分来更新Table1的MyBaseClass。
这应解决MyBaseClass生成的“必须具有唯一主键”错误。