You can try this mapping with 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. If you don't want that replace HasForeignKey
by: .Map(m => m.MapKey("ParentFKID"));
Edit
Using independent associations (i.e. 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.
Keep in mind that if you are going to create the database schema with Code-First EF will enforce all the FK constraints. 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.
I would suggest to avoid having navigation properties to the parent - customer, order and invoice - in the Note
class. 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. (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.)
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.
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. You would define only a single relationship between EntityWithNotes
and Note
. 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. I wouldn't even think about it. Or you put Customer
, Order
, Invoice
and EntityWithNotes
into different tables (Table-Per-Type (TPT) mapping). But then, TPT is not really known for the best performance. 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. 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.
I would suggest to stay away from this model and use separate tables for CustomerNotes
, OrderNotes
and InvoiceNotes
. If that isn't possible (existing and unchangable database schema?) it is questionable if Entity Framework is an appropriate tool for such a schema.