One to Many in Code First Entity Framework model - How do the relationships work?

code-first entity-framework

Question

Given the standard Northwind database (reduced for conciseness):

   [Table("Order Details")]
    public class OrderDetail : IValidatableObject
    {
        [Key, Column(Order = 1)]
        public int OrderID { get; set; }
        [Key, Column(Order = 2)]
        public int ProductID { get; set; }
        ...
    }
   [Table("Orders")]
    public class Order
        {
        public int OrderID { get; set; }
        ...
        public virtual ICollection<OrderDetail> OrderDetails { get; set; }
    }

I'm wondering about how this works exactly. I'm guessing that because the primary key in Order (OrderID) has foreign key in OrderDetails (OrderID) that is named the same, EF's rules correctly guess that they have a foreign-key/primary key relationship.

Is that correct?

Part two is another question:

I have an existing database where the foreign key is not named the same (change OrderId in OrderDetail to RecordNumber, for example - (I can't change the database)). In this case, I'm struggling trying to understand how to relate the two tables.

I'm using the Fluent API (and not the annotations as in above) and have something like this:

---OrderDetails

// set up the primary key
HasKey(t => new { t.RecordNumber, t.ProductID };

---Order

HasKey(t => t.OrderId);

HasRequired(t => t.OrderDetails).WithMany().HasForeignKey(t => t.OrderId)

(The last statement seems incredibly wrong, in that the only thing that HasForeignKey(...) seems to be able to relate to is the declared primary composite key)

I've also tried

HasMany((t => t.OrderDetails).WithMany()

which would seem to be different from the prior statement in that it makes it possible to have no OrderDetails.

Neither works.

The idea I am trying to express is that an order must have at least one OrderDetails - and I'm trying to be able to navigate thusly:

   Con.Orders.Single(o => o.OrderId == 1).OrderDetails

The problem I am having is that the foreign key I declared with HasForeignKey(...) does not relates to anything on Orders (and the code throws an appropriate exception - "Multiplicity is not valid"), and I am left not knowing how to accomplish my goal.

Any thoughts? I appreciate your help in advance.

1
4
7/1/2012 1:58:25 PM

Accepted Answer

I'm guessing that because the primary key in Order (OrderID) has foreign key in OrderDetails (OrderID) that is named the same, EF's rules correctly guess that they have a foreign-key/primary key relationship.

Yes, correct. The important part though is that Order has a navigation collection to OrderDetails. EF infers from this property (and the fact that there is no corresponding navigation property in OrderDetail refering to Order) that there is a one-to-many relationship between the two entities. Then the foreign key property is infered by naming conventions.

The idea I am trying to express is that an order must have at least one OrderDetails.

You can't define such a constraint in the mapping between model and database. You must ensure this in your application's business logic. In a one-to-many relationship the collection can have zero elements.

The correct mapping with Fluent API would be:

modelBuilder.Entity<Order>()
    .HasMany(order => order.OrderDetails)
    .WithRequired()
    .HasForeignKey(orderDetail => orderDetail.RecordNumber);
2
7/1/2012 2:32:16 PM


Related Questions





Related

Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow