Do I have to match both sides of the bidirectional relationship first in EF code?

Suppose I have the following entity classes:

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; }
}

      

How should they appear explicitly in code in Entity Framework 6? I want to be explicit about the display and not rely on automatic mapping conventions.

Option 1

Just map the local properties of both classes. This is how I would do it in Fluent NHibernate.

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

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

      

Option 2

Compare both sides of the relationship in both classes.

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);
  }
}

      

Option 3

Compare both sides of the relationship, but only in one of the classes. The code will be similar to option 2, only one of the two constructors will be empty.


Is there a difference between these parameters? If so, please also explain why I should or should not use the particular option.

+3


source to share


1 answer


I would choose option 3 .

In option 1, you may forget to match the opposite end of the association. In this simple example, it is clear that Order.Customer

both Customer.Orders

are the two ends of the same association. As the situation gets more complicated, it is not always obvious. It is also redundant code.

In option 2, you may have conflicting mappings. For example, when you have ...

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

      

... in OrderMap

, you will get a runtime exception telling you that both mappings do not match. Again, this is redundant code.



Thus, option 3 is dry and safe. The only problem is that it's a bit arbitrary where the mappings need to be tweaked. I tend to bind to displaying children in their parent mapping.

One more comment. You can add a primitive property CustomerId

to Order

. The display will look like this:

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

      

You now have complete control over both ends of the association and the foreign key name that will be used. In addition, there are some advantages of these foreign key associations rather than independent associations (no primitive foreign key). For example, the ability to create an association without having to retrieve the parent object from the database. You can just set the Id value.

+2


source







All Articles