I have found the answer. I'm posting it here in case it helps others.
Given the error was EF related, and the code compiled, I started with the assumption that it was most likely a configuration error.
To give some additional information: The PriceLineItem
class, at the focus of the error, can be nested within itself providing a tree structure. There are also some classes that inherit from PriceLineItem
, such as IssuePriceLineItem
.
Early when I started out with this new tree structure, I defined the following configuration manually in my DbContext
class using the fluent API:
modelBuilder.Entity<IssuePriceLineItem>()
.HasOptional(p => p.PriceLineItems)
.WithMany()
.HasForeignKey(c => c.ParentLineItemId);
This relic from the tinkering stage is where the error lies. You can see that it implies a many-to-many relationship. This can be fixed by altering line 2, or 2 and 3 of this config.
Correction 1:
modelBuilder.Entity<IssuePriceLineItem>()
.HasOptional(p => p.ParentLineItem)
.WithMany() /* implies ICollection<PriceLineItem> PriceLineItems */
.HasForeignKey(c => c.ParentLineItemId);
Correction 2:
modelBuilder.Entity<IssuePriceLineItem>()
.HasMany(p => p.PriceLineItems)
.WithOptional() /* implies ParentLineItem navigation property */
.HasForeignKey(c => c.ParentLineItemId);
Either way, in this specific case, I should have had it defined as self-referencing using PriceLineItem
and not IssuePriceLineItem
. If it had been self-referencing from the start, the erroneous config would have come to light earlier. Instead of sitting dormant until my recent refactoring kicked it into play.
In my mind the safest config definition is to be more explicit, as below:
modelBuilder.Entity<PriceLineItem>()
.HasOptional(p => p.ParentLineItem)
.WithMany(p => p.PriceLineItems)
.HasForeignKey(c => c.ParentLineItemId);
However, the best fix (IMO) is to remove this entry entirely. Since with the property names used, convention over configuration sufficiently takes care of this relationship definition