Reputation: 19641
I checked this one and other related questions, but couldn't find a working solution for my case.
So, I have 3 entities, PrintingMethod
, PrintingSubMethod
, and PrintPricing
. The rules are:
PrintingMethod
has a collection of PrintingSubMethod
. >> No problem with that.PrintingMethod
can have zero or one PrintPricing
.PrintingSubMethod
must have one PrintPricing
.PrintPricing
must be linked with either a PrintingMethod
or a PrintingSubMethod
.Here's the first two entities:
Public Class PrintingMethod
Public Property Id As Integer
Public Property Name As String
Public Property SupportsAdditionalColors As Boolean
Public Overridable Property SubMethods As ICollection(Of PrintingSubMethod)
Public Overridable Property AdditionalColorPricing As PrintPricing
End Class
Public Class PrintingSubMethod
Public Property Id As Integer
Public Property Name As String
Public Property PrintingMethodId As Integer
<ForeignKey("PrintingMethodId")>
Public Overridable Property ParentMethod As PrintingMethod
Public Overridable Property Pricing As PrintPricing
End Class
And here's an illustration of the third one:
Public Class PrintPricing
Public Property Id As Integer
<ForeignKey("LinkedSubMethod")>
Public Property SubMethodId As Integer
<ForeignKey("LinkedMethod")>
Public Property MethodId As Integer
Public Overridable Property LinkedSubMethod As PrintingMethodCode
Public Overridable Property LinkedMethod As PrintingMethod
End Class
So, is this possible to achieve using DataAnnotations or Fluent API? If not please feel free to suggest alternatives.
Notes:
Upvotes: 0
Views: 173
Reputation: 14034
Your relationship graph would look something like this, if I read your question right:
PrintingMethod [1:n] PrintingSubMethod
PrintingMethod [0..1:1] PrintPricing
PrintingSubMethod [0..1:1] PrintPricing
It's worth noting that a pure one to one relationship is not possible because the principal entity must always appear first (without the dependent entity existing which defeats the 1:1
constraint we're after). So a 1:1
in practice tends to be a one-to-zero-or-one-relationship.
Each
PrintingSubMethod
must have onePrintPricing
So enforcing this rule would require you to handle it at some other layer.
public class PrintPricing
{
[Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
// You may want to uncomment the "navigation" properties,
// but I'm going to leave it commented so you know this is
// not required for it to establish the relationship correctly,
// because this class represents the principal end of the relationship
// public virtual PrintingMethod Method { get; set; }
// public virtual PrintingSubMethod SubMethod { get; set; }
}
public class PrintingMethod
{
[Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
[ForeignKey("Pricing")] // foreign keys go on the dependent ends for 0:1 relationships
public int Id { get; set; }
public virtual List<PrintingSubMethod> SubMethods { get; set; }
public virtual PrintPricing Pricing { get; set; }
}
public class PrintingSubMethod
{
[Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
[ForeignKey("Pricing")]
public int Id { get; set; }
public virtual PrintingMethod Method { get; set; }
public virtual PrintPricing Pricing { get; set; }
}
You may also manually define foreign keys for the PrintingMethod [1:n] PrintingSubMethod
relationship if you'd like, but EF is smart enough to figure that by itself, so that's optional. I personally prefer defining foreign keys manually.
Upvotes: 1