【问题标题】:Entity Framework mapping two table columns to same related table Key实体框架将两个表列映射到同一个相关表键
【发布时间】:2013-07-19 17:38:38
【问题描述】:

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

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

在上述表模式中,ElementId1 和ElementId2 是外键 映射到Elements 表中的ElementId 并形成复合主键 Divergence 表。

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

我面临的问题是,当 EF 设计器生成模型时,它会在 Element 类中创建 2 组 ICollection<Element>,即 Elements 和 Elements1。

这不会给我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

这正确导致实体框架设计器中的1 <-> * 关系。我终于得到了一个Divergences DbSet,但DivergenceId 属性在代码中没有用,我仍然得到Element 类中的2 个集合。请务必注意,ElementId1 和 ElementId2 仍然构成复合主键。

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

【问题讨论】:

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


    【解决方案1】:

    而不是...

    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 命令。element1 和 element2 必须附加到状态 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();
    

    因此,如果没有 Divergence 实体,您将获得所需的结果,老实说,我会以这种方式使用它。我不知道有一种方法可以强制 EF 使用数据库优先方法创建该实体,除非您像以前那样引入一些人为的附加列。如果有一种方法可能是一种 hack,或者比仅使用 EF 的默认值更难实现和维护,那就是没有 Divergence 实体。

    但是,您可以考虑删除其中一个集合(只需在模型表面中删除它)。在我看来,在这个模型中同时拥有这两者有点令人困惑。或者至少将它们重命名为SourceElements 和TargetElements 例如:)

    【讨论】:

    • 很棒的斯劳马!就是这样......我将以这种方式实现它,因为正如您所说,没有内置功能可以按照我想要的方式进行映射。非常感谢您的关注! :)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-08-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-08-21
    • 1970-01-01
    相关资源
    最近更新 更多