一列用于 Entity Framework Core 中两个不同表的外键

Posted

技术标签:

【中文标题】一列用于 Entity Framework Core 中两个不同表的外键【英文标题】:One column used to foreign key to two different tables in Entity Framework Core 【发布时间】:2021-11-26 01:41:00 【问题描述】:

我有一些看起来像这样的实体:

public class Order

  [Key]
  [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
  public int OrderId get; set;
  public string Description get; set;
  public List<OrderDetail> OrderDetails get; set;


public class RoutedOrder

  [Key]
  [DatabaseGenerated(DatabaseGeneratedOption.None)]
  public int OrderId get; set;
  public int RoutingNumber get; set;
  public List<OrderDetail> OrderDetails get; set;


public class OrderDetail

  [Key]
  [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
  public int OrderDetailId get; set;

  [ForeignKey("Order,RoutedOrder")]
  public int OrderId get; set;

  public Order Order get; set;
  public RoutedOrder RoutedOrder get; set;

RoutedOrder 表是Order 表的“扩展”。并非Order 表中的所有行都最终在RoutedOrder 表中,但那些确实通过额外列获得了一些额外数据的行。但OrderId 列在两个表中的相关行的值相同。

因此,我不希望OrderDetail 中的两列指向每个实体。 (他们都使用OrderId。)

当我构建模型时,OrderDetail 会添加一个名为 RoutedOrderOrderId 的属性。这会导致我的数据库保存失败(因为没有这样的列)。

如何让 Entity Framework Core 使用 OrderId 作为两个关系的外键?

更新:

我希望能够查询Orders 并获得对应的OrderDetails 列表(在OrderDetail 表中有该订单的OrderId)。

我也希望能够对RoutedOrder 表执行相同的操作。 (查询RoutedOrders 并获取对应的OrderDetails 列表(在OrderDetail 表中有该RoutedOrder 的OrderId。)

此外,虽然OrderIdOrderRoutedOrder 中存在相同的值,但我目前在它们之间没有任何外键。 (我直接查找它们,而不是通过链接)。虽然如果我需要在那里添加 FK 关系来完成这项工作,我可以做到。

【问题讨论】:

Order 和 RoutedOrder 之间似乎存在 1 对 0 或 1 的关系。为什么是 OrderDetail 表?如果我理解,您创建一个订单记录,您可能会也可能不会创建一个 RoutedOrder 记录。如果以及在创建 RoutedOrder 记录时,只需将 Order 表中的 OrderId 值用作 RoutedOrder 表中的 OrderId 值即可。 @GHDevOps - 你说得对,那里存在 1 到(0 或 1)的关系。 OrderDetail 表包含从 Order/RoutedOrder 到 OrderDetail 的一对多关系的子记录。我希望这些记录在 Order 实体和 RoutedOrder 实体上都可用。有时我在查询 RoutedOrder 时没有获得其完整的 Order 记录(实际上它非常大)。所以 Order 有很多 OrderDetails。而且由于 RoutedOrder 具有相同的主键(OrderId),它也有许多 OrderDetails。 @Vaccano 您希望OrderDetail 中的OrderId 列成为OrderRoutedDetail 表的外键?这意味着当您有相应的OrderRoutedOrder 行时,您只能拥有OrderDetail 行。这也意味着单个Order 行不能有任何OrderDetail 行(因为缺少RoutedOrder 中的外键)。这就是你想要的吗? @Progman - 不完全是。我希望能够查询Orders 并获得相应的OrderDetails 列表(在OrderDetail 表中有该订单的OrderId)。我也希望能够对RoutedOrder 表做同样的事情。 (查询RoutedOrders 并获取对应OrderDetails 的列表(在OrderDetail 表中有该RoutedOrder 的OrderId。) 所以OrderRoutedOrder 形成一个表-per-type heirachy? docs.microsoft.com/en-us/ef/core/modeling/… 【参考方案1】:

经过更多的尝试和错误,但我明白了:

public class Order

  [Key]
  [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
  public int OrderId get; set;
  public string Description get; set;
  public List<OrderDetail> OrderDetails get; set;


public class RoutedOrder

  [Key]
  [DatabaseGenerated(DatabaseGeneratedOption.None)]
  public int OrderId get; set;
  public int RoutingNumber get; set;

  [InverseProperty("RoutedOrder ")]
  public List<OrderDetail> OrderDetails get; set;


public class OrderDetail

  [Key]
  [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
  public int OrderDetailId get; set;

  public int OrderId get; set;
  [ForeignKey("OrderId")]
  public Order Order get; set;
  [ForeignKey("OrderId")]
  public RoutedOrder RoutedOrder get; set;

变化是:

在 RoutedOrder 中添加一个 InverseProperty 属性,以便它知道要将其附加到哪个属性。 将ForeignKey 属性更改为导航属性并指向用于外键的字段/列。

这两个变化让它工作正常。

【讨论】:

以上是关于一列用于 Entity Framework Core 中两个不同表的外键的主要内容,如果未能解决你的问题,请参考以下文章

Entity Framework 6 不适用于时态表

Entity Framework 是不是可用于 Visual Studio 2008 Express Edition?

使用 Entity Framework 6.1 fluent API 创建唯一索引

用于简单数据模型和多对多关系的 Optimal Entity Framework 4 查询

在 Entity Framework Core 2.0 中执行存储过程

Entity Framework 4.3 - TPH 映射和迁移错误