【问题标题】:Should I map both sides of bidirectional relations in EF code first?我应该先在 EF 代码中映射双向关系的两侧吗?
【发布时间】:2014-09-18 08:30:44
【问题描述】:

假设我有以下实体类:

public class Customer {
  public int Id { get; set; }
  public virtual ICollection<Order> Orders { get; set; }
}

public class Order {
  public int Id { get; set; }
  public virtual Customer Customer { get; set; }
}

在 Entity Framework 6 流畅的代码优先映射中应该如何映射?我想明确映射,而不是依赖自动映射约定。

选项 1

只需映射两个类的本地属性。这就是我在 Fluent NHibernate 中的做法。

public class CustomerMap : EntityTypeConfiguration<Customer> {
  public CustomerMap() {
    HasMany(x => x.Orders);
  }
}

public class OrderMap : EntityTypeConfiguration<Order> {
  public OrderMap() {
    HasRequired(x => x.Customer);
  }
}

选项 2

在两个类中映射关系的两边。

public class CustomerMap : EntityTypeConfiguration<Customer> {
  public CustomerMap() {
    HasMany(x => x.Orders).WithRequired(x => x.Customer);
  }
}

public class OrderMap : EntityTypeConfiguration<Order> {
  public OrderMap() {
    HasRequired(x => x.Customer).WithMany(x => x.Orders);
  }
}

选项 3

映射关系的两侧,但仅在其中一个类中。代码与选项 2 类似,只是两个构造函数之一为空。


这些选项之间有什么区别吗?如果是,还请解释为什么我应该或不应该使用特定选项。

【问题讨论】:

  • EF 会自动检测这两个类之间的一对多关系,你不需要定义额外的映射。
  • @Masoud 在我不想依赖约定的问题中添加了注释。

标签: c# .net entity-framework ef-code-first entity-framework-6


【解决方案1】:

我会选择选项 3

在选项 1 中,您可能会忘记映射关联的反端。在这个简单的例子中,很明显Order.CustomerCustomer.Orders 是同一个关联的两端。当事情变得更复杂时,这并不总是显而易见的。而且,它是冗余代码。

在选项 2 中,您可能会有冲突的映射。例如,当您...

HasOptional(x => x.Customer).WithMany(x => x.Orders);

...在OrderMap 中,您将收到一个运行时异常,告诉您两个映射不匹配。再说一遍,它是冗余代码。

所以选项 3 是干燥且安全的。唯一的问题是在哪里配置映射有点随意。我倾向于坚持在他们父母的映射中映射孩子。

还有一条评论。您可能想在Order 中添加一个原始属性CustomerId。映射如下所示:

public class CustomerMap : EntityTypeConfiguration<Customer>
{
    public CustomerMap()
    {
        HasMany(x => x.Orders).WithRequired(x => x.Customer)
                              .HasForeignKey(o => o.CustomerId);
    }
}

现在您可以完全控制关联的两端和要使用的外键名称。除此之外,这些外键关联相对于独立关联(没有原始外键属性)还有一些优点。例如,无需从数据库中获取父对象即可建立关联的能力。您只需设置一个 Id 值即可。

【讨论】:

  • 感谢 cmets,但您似乎专注于编码风格。运行时行为如何?完全一样吗?
  • 好吧,我指出选项 2 可能会引发运行时异常。其余的都无所谓。有几种方法可以配置映射,最终产生完全相同的映射,因此运行时不会注意到任何差异。
  • 当然,映射本身的形状确实很重要。是否使用外键关联会影响启动时间:@​​987654321@(参见:2.4.1 使用外键关联降低视图生成成本)。
  • 我现在发现,如果从上下文中删除所有约定,选项 1 会导致不同的映射。似乎在那种情况下,EF 无法确定它们是同一关联的两端。我仍然在选项 2 和 3 之间犹豫不决。选项 2 的优点是更明确。在我看来,错误映射引发的异常也是一个优势。但选项 3 尊重 DRY。但这是一个不属于 SO 的编码风格问题。感谢您的帮助。
猜你喜欢
  • 2011-12-14
  • 1970-01-01
  • 1970-01-01
  • 2012-09-07
  • 2014-08-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多