2013-09-27 43 views
3

希望你能帮助EF代码第一次单外键多家长

我有3个(和更多的惊喜)表[Customer] [Order][Invoice]

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

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

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

我希望在每个3(和更多的惊喜)“父母创造的[Notes]集合“实体并配置每个实体以填充[Notes]表中的集合,其中父表的主键指向[ParentFKID]列。

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

这本质上是[CustomerNotes] [OrderNotes][InvoiceNotes]还这么我们没有复制表,以避免笔记表永远与外键日益增长的其他替代[Customer_ID] [Order_ID][Invoice_ID]

当然必须有办法用Fluent API映射来迎合这个问题,但是因为我对EF Code First和Fluent API都很陌生,所以我很难看到它。

我不在乎约束条件可能不可用 - 无论如何这都是可取的,而且这种结构看起来是不可能的。这肯定是一种常见的情况。

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

+1

您的解决方案可能是常见的,但是,这并不让任何少又臭又差。我建议你阅读这个https://www.simple-talk.com/sql/database-administration/five-simple--database-design-errors-you-should-avoid/的项目#1和#4。考虑你的笔记表可能增长速度为单个表的3倍......降低所有笔记查找的性能。此外,没有强制执行唯一约束..您可能正在使用GUID,这并不意味着您的应用程序(或人为错误)不能在多个表中插入相同的GUID。 –

回答

2

你可以试试这个映射用流利的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); 

我在这里想到的是ParentFKID财产为FK在Note类。 如果你不想通过更换 HasForeignKey.Map(m => m.MapKey("ParentFKID"));


编辑

使用独立协会(即使用MapKey没有在Note类FK属性)与共享的FK列呢不起作用,并在定义映射时抛出异常。


请记住,如果你要创建与代码优先EF数据库模式将强制所有的FK约束。您必须在数据库中手动禁用该功能(或者也可以使用基于代码的自定义迁移功能,但我不知道是否以及如何)。

我也预计ParentFKID列不可为空(因此WithRequired),因为我猜,没有父母的笔记没有意义。

我建议,以避免导航属性父 - 客户,订单和发票 - 在Note类。如果你想尝试加载一张纸条包括其母公司 - 你必须包括所有三个可能的父导航属性,因为你不能从一个给定的纸条,键入父有知道 - EF将创建INNER JOIN查询(由于所需关系并且因为它期望约束被执行),并且这将不返回结果,即使不是父母。 (你可以在INNER JOIN周围使用WithOptional代替WithRequired可能破解。 - 尽管在FK不允许NULL值EF将创建一个LEFT OUTER JOIN然后立即加载父母时)

我真的不知道,如果所有的将工作,并没有不希望的副作用。虽然你说这是一种常见的情况,但没有强制约束的情况下,EF没有明确支持关系。

其中EF将支持更好的场景是具有携带Notes收集和CustomerOrderInvoice从导出基实体EntityWithNotes。您只需定义EntityWithNotesNote之间的单一关系。在数据库方面你可以选择把CustomerOrderInvoice到一个表(表每层次(TPH)映射),它老老实实听起来很可笑考虑这些实体的商业含义有何不同。我甚至不会去想它。或者你把CustomerOrderInvoiceEntityWithNotes到不同的表(表每类型(TPT)映射)。但是,TPT并不以最佳性能着称。我不会认真考虑这个重要的实体,也可能是快速增长的表格。

编辑

虽然与共享的FK财产如初作品显示我得到其他异常时,我删除的数据库中的外键约束执法的映射。虽然我可以将数据保存成功,我得到有关ObjectContext的不一致的状态异常,因为很明显的情况下总是期望的约束强制执行。

我建议远离这种模式,并使用单独的表CustomerNotes,OrderNotesInvoiceNotes。如果这是不可能的(现有的和不可更改的数据库模式?),实体框架是否适合这种模式是合适的工具,这是值得怀疑的。

+0

有趣。 [你可能记得](http://stackoverflow.com/q/13953675/861716)我已经与这些_多态关联进行了很多的斗争_。经过多番思考,我目前倾向于为每个家长创建单独的子表。我也怀疑“所有这些是否会奏效”,恐怕EF会对共享的外键感到不满,但我必须在本周末的某个时候尝试。 –

+0

@GertArnold:我打算让我最后一段中的EntityWithNotes成为一个真实的实体(例如它自己的DbSet),而不仅仅是其他三个实体的基础。如果'Notes'集合位于该基本实体中,并且'Note'中的FK直接引用它,而不是其他三个实体,那么我相信它会起作用。我认为这不是多态关联的情况。我对共享的FK也不太确定。共享导航属性不能正常工作,但共享FK ...我的小心提示:它的工作原理:)(明天我会测试它。) – Slauma

+0

@GertArnold:我的提示只有50%正确:共享的FK使用外键关联('HasForeignKey'),但它不适用于独立关联('MapKey'),这有点奇怪,但使用三次具有相同列名称的MapKey会抛出关于不明确名称的异常。无论如何,真正的问题是删除数据库中的强制执行,导致其他异常(请参阅上面的编辑),我无法从中逃脱。 – Slauma