3

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

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

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

我使用Database First 方法,在 SQL Server Management Studio 中创建表,然后我做了一个Update Model from Database...在 Entity Framework Designer 中创建表。

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

在此处输入图像描述

这没有给我一个DivergencesDbSet。

我想要的是一个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

这正确地导致了1 <-> *实体框架设计器中的关系。我终于得到了一个DivergencesDbSet 但DivergenceId属性在代码中没有用,我仍然得到了Element类中的 2 个集合。重要的是要注意ElementId1ElementId2构成复合主键。

您认为映射这种特定情况的正确方法是什么?感谢您的输入。

4

1 回答 1

2

Instead of...

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

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

... you could actually use:

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

Database.SaveChanges();

This will create exactly the same SQL INSERT statements to the link table without the need of having a Divergence entity. (Change tracking will recognize that you changed the relationship by adding an item to the collection and infer the necessary SQL commands from this change. element1 and element2 must be attached to the context in state Unchanged, but that is also required for your original code in order to work correctly.)

Also, instead of ...

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

... you can fetch the columns from the Divergences table like so:

var divergences = Database.Elements.Where(e => e.ElementId == 7)
    .SelectMany(e1 => e1.Elements.Select(e2 => new
    {
        ElementId1 = e1.ElementId,
        ElementId2 = e2.ElementId,
    }))
    .ToList();

So, you will get your desired results without the Divergence entity and honestly I would use it this way. I'm not aware of a way to force EF to create that entity with database first approach, unless you introduce some artificial additional column like you did. If there is a way it is probably a hack or more difficult to achieve and maintain than just working with EF's default, that is without a Divergence entity.

However, you could consider to remove one of the collections (just delete it in the model surface). Having both is a bit confusing in this model in my opinion. Or at least rename them to SourceElements and TargetElements for example :)

于 2013-07-19T18:34:18.187 回答