4

给定标准的 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 上的任何内容都不相关(并且代码引发了适当的异常 - “多重性无效”),我不知道如何来完成我的目标。

有什么想法吗?我提前感谢您的帮助。

4

1 回答 1

2

我猜是因为 Order (OrderID) 中的主键在 OrderDetails (OrderID) 中具有相同名称的外键,所以 EF 的规则正确猜测它们具有外键/主键关系。

是,对的。重要的部分是它Order有一个到 s 的导航集合OrderDetailOrderDetailEF 从这个属性(以及在引用 时没有相应的导航属性的事实)推断出Order两个实体之间存在一对多的关系。然后通过命名约定推断外键属性。

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

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

Fluent API 的正确映射是:

modelBuilder.Entity<Order>()
    .HasMany(order => order.OrderDetails)
    .WithRequired()
    .HasForeignKey(orderDetail => orderDetail.RecordNumber);
于 2012-07-01T14:32:16.333 回答