我应该先在EF代码中映射双向关系的两面吗?

时间:2014-09-18 08:30:45

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

假设我有以下实体类:

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,两个构造函数中只有一个是空的。


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

1 个答案:

答案 0 :(得分:2)

我会选择选项3

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

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

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

...在OrderMap中,您将收到一个运行时异常,告诉您两个映射都不匹配。而且,这是多余的代码。

因此选项3是干燥且安全的。唯一的问题是它在配置映射的位置有点随意。我倾向于坚持在父母的映射中映射孩子。

还有一条评论。您可能希望在CustomerId中添加原始属性Order。映射看起来像:

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

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