多个可选的一对一关系,其中需要一个(任何)关系

时间:2017-12-02 02:57:04

标签: c# .net vb.net entity-framework one-to-one

我查看了this one和其他相关问题,但无法为我的案例找到合适的解决方案。

所以,我有3个实体,PrintingMethodPrintingSubMethodPrintPricing。规则是:

  • PrintingMethod有一个PrintingSubMethod的集合。 >>没问题。
  • PrintingMethod 可以 零或一个PrintPricing
  • 每个PrintingSubMethod 必须 一个PrintPricing
  • 每个PrintPricing 必须 链接 PrintingMethod a PrintingSubMethod

这是前两个实体:

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

以下是第三个例子:

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

那么,这可能是使用DataAnnotations或Fluent API实现的吗?如果没有,请随时提出替代方案。

注意:

  • 为简洁起见,删除了不相关的字段和DataAnnotations。
  • 我正在使用Entity Framework 6.0。
  • 虽然我的代码是在VB中,但也欢迎任何C#答案。

1 个答案:

答案 0 :(得分:1)

如果我正确地阅读了你的问题,你的关系图就会是这样的:

PrintingMethod       [1:n]  PrintingSubMethod
PrintingMethod    [0..1:1]  PrintPricing   
PrintingSubMethod [0..1:1]  PrintPricing

值得注意的是,纯粹的一对一关系是不可能的,因为主体必须始终首先出现(没有存在的依赖实体,这会破坏我们所追求的1:1约束)。因此,实际上1:1往往是一对一或零关系。

  

每个PrintingSubMethod必须有一个PrintPricing

因此,强制执行此规则将要求您在其他层处理它。

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; }
}

如果您愿意,您也可以手动定义PrintingMethod [1:n] PrintingSubMethod关系的外键,但EF足够聪明,可以自行计算,因此这是可选的。我个人更喜欢手动定义外键。