实体框架将两个表列映射到相同的相关表Key

时间:2013-07-19 17:38:38

标签: entity-framework mapping composite-primary-key ef-database-first entity-framework-designer

我的情况是我有一个名为Elements的表。现在我正在创建一个名为Divergences的表,它将基本存储Elements对。 Divergence的目的是检查两个Elements是否有不同的答案。

Element               Divergence
---------             ----------
ElementId             ElementId1
                      ElementId2

在上表模式中,ElementId1ElementId2外键映射到ElementId表格中的Elements并形成 Divergence表的复合主键

我使用数据库优先方法,我在SQL Server Management Studio中创建表,之后我在实体框架设计器中执行Update Model from Database...

我面临的问题是,当EF Designer生成模型时,它会在ICollection<Element>类中创建2组Element,即ElementsElements1

enter image description here

这不会给我Divergences DbSet。

我想要的是Divergence课程,我会在代码中执行以下操作:

Divergence d = new Divergence();
d.Element1 = element1;
d.Element2 = element2;

Database.Divergences.Add(d);
Database.SaveChanges();

以及后来:

Element e = Database.Elements.Single(e => e.ElementId == 7);

var divergences = e.Divergences;

我尝试在Divergence表中添加一个新列,如下所示:

Element               Divergence
---------             ------------
ElementId             DivergenceId
                      ElementId1
                      ElementId2

这在Entity Framework Designer中正确导致1 <-> *关系。我终于得到一个Divergences DbSet,但DivergenceId属性在代码中没用,我仍然在Element类中获得了2个集合。请务必注意ElementId1ElementId2仍构成复合主键。

您认为绘制这种特定情况的正确方法是什么?感谢您的投入。

1 个答案:

答案 0 :(得分:2)

而不是......

Divergence d = new Divergence();
d.Element1 = element1;
d.Element2 = element2;

Database.Divergences.Add(d);
Database.SaveChanges();

......你实际上可以使用:

element1.Elements = new List<Element>();
// if that collection isn't already instantiated, for example in the constructor
element1.Elements.Add(element2);

Database.SaveChanges();

这将为链接表创建完全相同的SQL INSERT语句,而无需具有Divergence实体。 (更改跟踪将识别您通过向集合添加项目并从此更改推断必要的SQL命令来更改关系。element1element2必须附加到状态{{1}中的上下文},但为了正常工作,原始代码也需要这样做。)

此外,而不是......

Unchanged

...您可以像这样从Element e = Database.Elements.Single(e => e.ElementId == 7); var divergences = e.Divergences; 表中获取列:

Divergences

因此,如果没有var divergences = Database.Elements.Where(e => e.ElementId == 7) .SelectMany(e1 => e1.Elements.Select(e2 => new { ElementId1 = e1.ElementId, ElementId2 = e2.ElementId, })) .ToList(); 实体,您将获得所需的结果,老实说,我会以这种方式使用它。我不知道有一种方法可以强制EF使用数据库优先方法创建该实体,除非你像你一样引入一些人为的附加列。如果有一种方法可能是黑客攻击或者更难以实现和维护,而不仅仅是使用EF的默认值,那就是没有Divergence实体。

但是,您可以考虑删除其中一个集合(只需在模型表面中删除它)。在我看来,两者在这个模型中有点混乱。或者至少将它们重命名为DivergenceSourceElements,例如:)