给定标准的Northwind数据库(简化为简洁):
[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; }
}
我想知道它是如何工作的.我猜测,因为Order(OrderID)中的主键在OrderDetails(OrderID)中具有相同的外键,EF的规则正确地猜测它们具有外键/主键关系.
那是对的吗?
第二部分是另一个问题:
我有一个现有的数据库,其中外键的名称不相同(例如,将OrderDetail中的OrderId更改为RecordNumber – (我无法更改数据库)).在这种情况下,我正在努力了解如何关联这两个表.
我正在使用Fluent API(而不是上面的注释)并且具有以下内容:
---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)
(最后一个语句看起来非常错误,因为HasForeignKey(…)似乎唯一能够与之相关的是声明的主复合键)
我也试过了
HasMany((t => t.OrderDetails).WithMany()
这似乎与先前的陈述不同,因为它可以没有OrderDetails.
两者都不起作用.
我试图表达的想法是订单必须至少有一个OrderDetails – 我正试图能够这样导航:
Con.Orders.Single(o => o.OrderId == 1).OrderDetails
我遇到的问题是我用HasForeignKey(…)声明的外键与Orders上的任何内容都没有关系(并且代码抛出了一个适当的异常 – “Multiplicity无效”),我不知道如何实现我的目标.
有什么想法吗?我提前感谢您的帮助.
最佳答案
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.
是,对的.但重要的是,Order有OrderDetails的导航集合. EF从这个属性推断(以及OrderDetail中没有相应的导航属性,引用Order)这两个实体之间存在一对多的关系.然后,外键属性受命名约定的影响.
The idea I am trying to express is that an order must have at least
one OrderDetails.
您无法在模型和数据库之间的映射中定义此类约束.您必须在应用程序的业务逻辑中确保这一点.在一对多关系中,集合可以具有零元素.
使用Fluent API的正确映射是:
modelBuilder.Entity<Order>()
.HasMany(order => order.OrderDetails)
.WithRequired()
.HasForeignKey(orderDetail => orderDetail.RecordNumber);