简体   繁体   English

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

[英]EF Code First Single foreign key to multiple parents

Hope you can help 希望你能帮忙

I have 3 (and more to come) tables [Customer] [Order] and [Invoice] . 我有3个(以及更多)表[Customer] [Order][Invoice]

All of these tables have an ID column [ID - Guid] . 所有这些表都有一个ID列[ID - Guid]

I have a table [Notes] and it is comprised of 2 columns (for brevity): - 我有一个表[Notes] ,它由2列(为简洁起见)组成: -

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

I wish to create a collection of [Notes] on each of the 3 (and more to come) "parent" entities and configure each of these entities to populate the collection from the [Notes] table where the primary key of the parent table in question is pointing to the [ParentFKID] column. 我希望在3个(以及更多来的)“父”实体中的每一个上创建[Notes]的集合,并配置这些实体中的每一个以从[Notes]表填充集合,其中父表的主键在问题是指向[ParentFKID]列。

So essentially the column [ParentFKID] is a foreign key, but a foreign key to multiple other tables. 所以基本上列[ParentFKID]是外键,但是是多个其他表的外键。 This is possible as we are using GUID keys. 这是可能的,因为我们使用GUID键。

This is essentially so we don't have replicated tables of [CustomerNotes] [OrderNotes] and [InvoiceNotes] AND ALSO to avoid the other alternative of having the notes table forever growing with the foreign keys [Customer_ID] [Order_ID] and [Invoice_ID] 这基本上是这样我们没有[CustomerNotes] [OrderNotes][InvoiceNotes]复制表,而且[InvoiceNotes]避免使用外键[Customer_ID] [Order_ID][Invoice_ID]使Notes表永远增长的另一种选择。

Surely there must be a way to cater for this with a Fluent API mapping but as I'm so new to EF Code First and the Fluent API then I'm struggling to see it. 肯定有一种方法可以通过Fluent API映射来满足这一要求,但由于我是EF Code First和Fluent API的新手,所以我很难看到它。

I don't care that the constraints may be unavailable - this is preferable anyway and seemingly impossible with the structure. 我并不关心约束可能无法获得 - 无论如何这是优选的,并且结构似乎是不可能的。 This surely is a common scenario. 这肯定是一种常见的情况。

Can anyone help and provide an example of how to configure the entities for the model to enable this scenario ? 任何人都可以帮助并提供如何为模型配置实体以启用此方案的示例吗?

You can try this mapping with Fluent API: 您可以使用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);

I expect here that ParentFKID is a property for the FK in your Note class. 我希望在这里, ParentFKIDNote类中FK的属性 If you don't want that replace HasForeignKey by: .Map(m => m.MapKey("ParentFKID")); 如果您不希望通过以下方式替换 HasForeignKey.Map(m => m.MapKey("ParentFKID"));


Edit 编辑

Using independent associations (ie using MapKey without a FK property in the Note class) with a shared FK column does not work and throws exceptions when the mapping is defined. 在共享FK列中使用独立关联(即在Note类中使用不带FK属性的MapKey )不起作用,并在定义映射时抛出异常。


Keep in mind that if you are going to create the database schema with Code-First EF will enforce all the FK constraints. 请记住,如果要使用Code-First 创建数据库模式,EF将强制执行所有FK约束。 You have to disable that manually in the database then (or maybe it's also possible with a code-based customized migration, but I don't know if and how). 您必须在数据库中手动禁用它(或者也可以使用基于代码的自定义迁移,但我不知道是否以及如何)。

I also expected that the ParentFKID column is not nullable (hence WithRequired ) because, I guess, a note without a parent doesn't make sense. 我还期望ParentFKID列不可为空(因此WithRequired )因为,我猜,没有父节点的音符没有意义。

I would suggest to avoid having navigation properties to the parent - customer, order and invoice - in the Note class. 我建议避免在Note类中为父级 - 客户,订单和发票 - 提供导航属性。 If you would attempt to load a note including its parent - and you had to include all three possible parent navigation properties because you can't know from a given note which type the parent has - EF will create INNER JOIN queries (due to the required relationship and because it expects that the constraint is enforced) and this will return no result, even not the parent. 如果您尝试加载包含其父项的注释 - 并且您必须包含所有三个可能的父导航属性,因为您无法从给定的注释中知道父项具有哪种类型 - EF将创建INNER JOIN查询(由于所需关系,因为它期望强制执行约束),这将不返回任何结果,即使不是父项。 (You could possibly hack around the INNER JOIN by using WithOptional instead of WithRequired - despite of the FK not allowing NULL values. EF would create a LEFT OUTER JOIN then when eager loading the parents.) (你能不能砍周围的INNER JOIN使用WithOptional代替WithRequired -尽管的FK不允许NULL值EF将创建一个。 LEFT OUTER JOIN那么渴望时加载的父母。)

I'm really not sure if all that will work and doesn't have unwished side effects. 我真的不确定是否所有这些都能奏效并且没有副作用。 Although you are saying it's a common scenario EF does not have explicit support for relationships without enforced constraints. 虽然您说这是一种常见情况,但EF没有明确支持没有强制约束的关系。

A scenario which EF would support better is having a base entity EntityWithNotes that carries the Notes collection and which Customer , Order and Invoice derive from. EF更好地支持的场景是拥有一个基本实体EntityWithNotes ,它携带Notes集合以及CustomerOrderInvoice派生自哪个。 You would define only a single relationship between EntityWithNotes and Note . 您只需在EntityWithNotesNote之间定义一个关系。 On database side you have the choice to put Customer , Order and Invoice into a single table (Table-Per-Hierarchy (TPH) mapping) which honestly sounds ridiculous considering how different the business meaning of those entities is. 在数据库方面,您可以选择将CustomerOrderInvoice放入单个表(Table-Per-Hierarchy(TPH)映射)中,考虑到这些实体的业务含义有多么不同,这听起来很荒谬。 I wouldn't even think about it. 我甚至都不会想到它。 Or you put Customer , Order , Invoice and EntityWithNotes into different tables (Table-Per-Type (TPT) mapping). 或者您将CustomerOrderInvoice EntityWithNotes放入不同的表(Table-Per-Type(TPT)映射)。 But then, TPT is not really known for the best performance. 但是,TPT并不是最出色的表现。 I wouldn't really consider this for such important entities and probably fast growing tables. 我不会真的考虑这个重要的实体,也可能是快速增长的表格。

Edit 编辑

While the mapping with shared a FK property like shown at the beginning works I get other exceptions when I remove the enforcement of the foreign key constraints in the database. 虽然在开头显示的共享FK属性的映射工作时,当我删除数据库中的外键约束的强制执行时,我得到其他异常。 Although I can save data successfully I get exceptions about inconsistent states of the ObjectContext because apparently the context always expects that the constraints are enforced. 虽然我可以成功保存数据但是我得到了关于ObjectContext不一致状态的异常,因为显然上下文总是期望强制执行约束。

I would suggest to stay away from this model and use separate tables for CustomerNotes , OrderNotes and InvoiceNotes . 我建议远离这个模型,并为CustomerNotesOrderNotesInvoiceNotes使用单独的表。 If that isn't possible (existing and unchangable database schema?) it is questionable if Entity Framework is an appropriate tool for such a schema. 如果那是不可能的(现有的和不可交换的数据库模式?),那么实体框架是否适合这种模式的工具是值得怀疑的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM