且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

一对多的代码第一实体框架模型 - 关系如何工作?

更新时间:2022-11-05 09:38:56


我猜,因为订单中的主键(OrderID)在OrderDetails(OrderID)中具有
外键,名称相同,EF的
规则正确地猜测他们有一个外键/主键
关系。


是的,正确。重要的是,订单有一个导航集合到 OrderDetail s。 EF从这个属性推断(事实上,在 OrderDetail 中没有相应的导航属性引用订单)那里是两个实体之间的一对多关系。然后外键属性受命名约定的限制。


我想表达的想法是,订单必须至少有
一个OrderDetails。


您不能在模型和数据库之间的映射中定义这样的约束。您必须确保在应用程序的业务逻辑中。在一对多关系中,集合可以有零个元素。



使用Fluent API的正确映射将是:

  modelBuilder.Entity< Order>()
.HasMany(order => order.OrderDetails)
.WithRequired()
.HasForeignKey (orderDetail => orderDetail.RecordNumber);


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.

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