Reputation: 285
I'm using EF6 and code-first approach to implement custom properties for products belongs to certain categories (or any other classification tree: aspect). I'd like to implement the following database structure through components.
Direct link to the image: image
(The relation links moved to the corresponding primary/foreign key in the image)
When I added the AssignedOption navigational property to the Aspects class/table, I got the following exception during seeding:
"Unable to determine the principal end of an association between the types 'storeBeacon.Models.Aspect' and 'storeBeacon.Models.AspectOption'. The principal end of this association must be explicitly configured using either the relationship fluent API or data annotations."
The code of the related classes are the following:
Public Class Aspect
<Key>
Public Property Id As Integer
Public Property Name As String
Public Property Type As String
Public Property CardinalityMinimum As Byte
Public Property CardinalityMaximum As Byte
<ForeignKey("AssignedOptionId")>
Public Overridable Property AssignedOption As AspectOption
Public Property AssignedOptionId As Integer?
End Class
Public Class AspectOption
<Key>
Public Property Id As Integer
<ForeignKey("AspectId")>
Public Overridable Property Aspect As Aspect
Public Property AspectId As Integer
<ForeignKey("ParentId")>
Public Overridable Property Parent As AspectOption
Public Property ParentId As Integer?
Public Property Label As String
End Class
So can you please tell me how to fix this problem without fluent API if possible?
Upvotes: 1
Views: 213
Reputation: 16149
It looks like you're trying to set them up as a one-to-one relationship. In which case you'll need to pick one of them to be the primary table of the relationship, and the other to use a FK into it. Because right now you can't use 2 FKs to point to each other, since it confuses Entity Framework.
EDIT: Based on the comment, I've figured out what you need to do. I wrote my code in C#, but I'm sure it's easily translatable to VB.
In Aspect
:
public int AssignedOptionID { get; set; }
[ForeignKey("AssignedOptionID"), InverseProperty("Aspects")]
public virtual AspectOption AssignedOption { get; set; }
public virtual List<AspectOption> AspectOptions { get; set; }
In AspectOption
:
[ForeignKey("AspectID"), InverseProperty("AspectOptions")]
public virtual Aspect Aspect { get; set; }
[ForeignKey("ParentID")]
public virtual AspectOption Parent { get; set; }
public virtual List<Aspect> Aspects { get; set; }
In your DbContext's OnModelCreating
method (yes, you have to do something in Fluent API, since otherwise it will throw an exception saying that there are multiple cascade paths):
modelBuilder.Entity<Aspect>()
.HasMany(a => a.AspectOptions)
.WithRequired(a => a.Aspect)
.WillCascadeOnDelete(false);
Upvotes: 2