EF Code First单个外键给多个父母

时间:2013-09-27 14:08:31

标签: c# entity-framework ef-code-first

希望你能帮忙

我有3个(以及更多)表[Customer] [Order][Invoice]

所有这些表都有一个ID列[ID - Guid]

我有一个表[Notes],它由2列组成(为简洁起见): -

[ID - Guid]
[ParentFKID - Guid]
[Comment - String]

我希望在3个(以及更多来的)"父母"中的每一个上创建一个[Notes]的集合。实体并配置这些实体中的每一个以从[Notes]表填充集合,其中所讨论的父表的主键指向[ParentFKID]列。

基本上,列[ParentFKID]是外键,但是是多个其他表的外键。这是可能的,因为我们使用GUID键。

这基本上是这样的,我们不会复制[CustomerNotes] [OrderNotes][InvoiceNotes]的表格,以避免使用外键{{1}使备注表永远增长的另一种选择。 }和[Customer_ID] [Order_ID]

肯定有一种方法可以通过Fluent API映射来满足这一要求,但由于我是EF Code First和Fluent API的新手,所以我很难看到它。

我不在乎约束可能无法获得 - 无论如何这都是可取的,而且结构似乎是不可能的。这肯定是一种常见的情况。

任何人都可以提供帮助并提供如何配置模型实体以启用此方案的示例吗?

1 个答案:

答案 0 :(得分:2)

您可以使用Fluent API尝试此映射:

modelBuilder.Entity<Customer>()
    .HasMany(c => c.Notes)
    .WithRequired()
    .HasForeignKey(n => n.ParentFKID);

modelBuilder.Entity<Order>()
    .HasMany(o => o.Notes)
    .WithRequired()
    .HasForeignKey(n => n.ParentFKID);

modelBuilder.Entity<Invoice>()
    .HasMany(i => i.Notes)
    .WithRequired()
    .HasForeignKey(n => n.ParentFKID);

我希望ParentFKIDNote中的HasForeignKey属性如果您不希望将.Map(m => m.MapKey("ParentFKID"));替换为MapKey


修改

在共享FK列中使用独立关联(即在Note类中使用ParentFKID而不使用FK属性)不起作用,并在定义映射时抛出异常。


请记住,如果您要使用Code-First EF 创建数据库架构,则会强制执行所有FK约束。您必须在数据库中手动禁用它(或者也可以使用基于代码的自定义迁移,但我不知道是否以及如何)。

我还期望WithRequired列不可为空(因此Note)因为,我想,没有父母的笔记没有意义。

我建议避免在INNER JOIN课程中为父母 - 客户,订单和发票设置导航属性。如果您尝试加载包含其父项的注释 - 并且您必须包含所有三个可能的父导航属性,因为您无法从给定注释中了解父项具有哪种类型 - EF将创建INNER JOIN个查询(到期)到所需的关系,因为它希望强制执行约束),这将不返回任何结果,即使不是父。 (你可能会使用WithOptional代替WithRequired来破解NULL - 尽管FK不允许LEFT OUTER JOIN值.EF会创建一个EntityWithNotes然后当急切地加载父母时。)

我真的不确定这一切是否有效并且没有不受欢迎的副作用。虽然您说这是一种常见情况,但EF没有明确支持没有强制约束的关系。

EF会更好地支持的一个场景是拥有一个带有Notes集合的基础实体CustomerOrderInvoiceEntityWithNotes派生自Note 。您只能在CustomerOrder之间定义一个关系。在数据库方面,您可以选择将InvoiceCustomerOrder放入单个表(Table-Per-Hierarchy(TPH)映射)中,考虑到业务的不同,这听起来很荒谬这些实体的意义是。我甚至都不会想到它。或者您将InvoiceEntityWithNotesObjectContext CustomerNotes放入不同的表格(每个类型的表格(TPT)映射)。但是,TPT并不是最出色的表现。对于这些重要的实体以及可能快速增长的表格,我不会真的考虑这个。

修改

虽然在开头显示的共享FK属性的映射工作时,当我删除数据库中的外键约束的强制执行时,我得到其他异常。虽然我可以成功保存数据,但我得到了OrderNotes的不一致状态的异常,因为显然上下文总是希望强制执行约束。

我建议远离此模型,并为InvoiceNotes,{{1}}和{{1}}使用单独的表格。如果那是不可能的(现有的和不可交换的数据库模式?),那么实体框架是否适合这种模式的工具是值得怀疑的。