I have the following tables in my database:
Product ResourceAssociation
------- ------------------
Name /-------> Id
ResourceAssociation_Id ------/ SomeProperty
So Product has a ResourceAssociation_Id, which is a FK to the ResourceAssociation table.
This is a legacy application that had an Entity Framework 6 map that contained this piece of code:
HasOptional(t => t.ResourceAssociation).WithOptionalDependent().WillCascadeOnDelete(true);
I'm looking to port this to EF Core. EF Core doesn't have the HasOptional anymore, it seems. I've tried this:
builder.HasOne(t => t.ResourceAssociation)
.WithOne().HasForeignKey("ResourceAssociation_Id")
.IsRequired(false)
.OnDelete(DeleteBehavior.Cascade);
I've also tried replacing the WithOne with WithMany. But it doesn't work.
When I try to create a new Product, without a ResourceAssociation (because it isn't required), EF Core still tells me my ModelState is invalid because the ResourceAssociation is null.
I can't specify the property in WithOne (e.g. WithOne(x => x.Product)) because ResourceAssociation is a table that will also be used for other tables (for example Brand also has a ResourceAssociation_Id column pointing to that table).
Is this kind of setup even possible in EF Core? Or will I have to add the different navigation properties to my ResourceAssociation class (ie Product, Brand,...)?
In EF Core, HasOne / WithOne (even with navigation properties) are not enough for determining which is the principal and which is the dependent entity in the one-to-one relationship (for one-to-many the one is always principal, many is the dependent, and for many-to-many there is not principal/dependent).
Because of that, the generic type argument of HasForeignKey / HasPrincipalKey is required for determination of respectively dependent / principal entity. This is actually explained in the Other Relationship Patterns - One-to-one EF Core documentation topic:
When configuring the relationship with the Fluent API, you use the
HasOneandWithOnemethods.When configuring the foreign key you need to specify the dependent entity type - notice the generic parameter provided to
HasForeignKeyin the listing below. In a one-to-many relationship it is clear that the entity with the reference navigation is the dependent and the one with the collection is the principal. But this is not so in a one-to-one relationship - hence the need to explicitly define it.
So what you need here is to specify Product as being the dependent of the relationship, along with the FK property / column name:
builder.HasOne(t => t.ResourceAssociation)
.WithOne() // ok, no navigation
.HasForeignKey<Product>("ResourceAssociation_Id") // FK name in the dependent
// ^^^ the dependent entity of the relationship
.IsRequired(false)
.OnDelete(DeleteBehavior.Cascade);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With