自引用 1 对多关系

Self referencing 1 to many relation

我有以下实体:

 public class TravelCoverageType
 {
     public int Code { get; set; }

     public virtual TravelCoverageType PreventedBy { get; set; }

     public ICollection<TravelCoverageType> PreventCoverages { get; set;}
     ...
 }

每个TravelCoverageType可以防止0个或更多TravelCoverageType个。

我正在使用流利的 API,但不知道如何描述这种关系。

我试过:

public TravelCoverageTypeConfiguration()
        {
            ToTable(ConfigConstants.TypeTablePrifix + typeof(TravelCoverageType).Name + "s");
            HasKey(ct => ct.Code);

            HasMany(tc => tc.PreventCoverages)
                .WithOptional(tc=>tc.PreventedBy)
                .HasForeignKey(tc => tc.Code);
        }  

但我收到以下错误:

System.Data.Entity.Edm.EdmAssociationType: : Multiplicity conflicts with the referential constraint in Role 'TravelCoverageType_PreventCoverages_Source' in relationship 'TravelCoverageType_PreventCoverages'. Because all of the properties in the Dependent Role are non-nullable, multiplicity of the Principal Role must be '1'.

System.Data.Entity.Edm.EdmAssociationEnd: : Multiplicity is not valid in Role 'TravelCoverageType_PreventCoverages_Target' in relationship 'TravelCoverageType_PreventCoverages'. Because the Dependent Role refers to the key properties, the upper bound of the multiplicity of the Dependent Role must be '1'.

(我添加了 PreventedBy 来简化关系的定义,我真的不需要它)

这是怎么做到的?

是否必须使用 Fluent API 来完成?我碰巧不太了解它,但您可以改为使用数据注释执行以下操作:

public class TravelCoverageType
{
     [Key]
     public int Code { get; set; }

     [ForeignKey("PreventedBy")]
     public int? PreventedByID { get; set; }

     public virtual TravelCoverageType PreventedBy { get; set; }

     public ICollection<TravelCoverageType> PreventCoverages { get; set;}
}

编辑:仔细观察您的问题,我注意到您正试图将 Code 属性 用作 FK:

.HasForeignKey(tc => tc.Code);

EF 根本不喜欢这样,因为您看到的例外情况(它告诉您,如果您也想将主键设为 FK,则只能针对 1:1,不是 1:Many)。尝试向 class 添加一个新的 属性(就像我在上面的数据注释示例中所做的那样),然后将配置更改为:

HasMany(tc => tc.PreventCoverages)
.WithOptional(tc => tc.PreventedBy)
.HasForeignKey(tc => tc.PreventedByID);

问题是您也将实体的 PK 用作 FK,但在配置一对多关系时不能这样做。如果你想创建一个自引用的一对多关系并且你只想有一个与该关系的一侧相关的导航 属性 (我认为这是你想要的场景),你的模型将是像这样:

public class TravelCoverageType
{
   public int Code { get; set; }

   public ICollection<TravelCoverageType> PreventCoverages { get; set;}
   ...
}

关系的配置是这样的:

 HasMany(tc => tc.PreventCoverages).WithOptional();

现在,如果您想与关系的双方一起工作,您需要添加 PreventedBy 导航 属性,就像在您显示的模型中一样。在这种情况下,您可以这样配置关系:

HasMany(tc => tc.PreventCoverages).WithOptional(tc => tc.PreventedBy);

最后,如果你也想使用 FK 属性,在这种情况下你需要在你的实体中添加另一个 属性 相同类型的 PK:

public class TravelCoverageType
{
 public int Code { get; set; }

 public int  PreventedById { get; set; }
 public virtual TravelCoverageType PreventedBy { get; set; }

 public ICollection<TravelCoverageType> PreventCoverages { get; set;}
 ...
}

你的关系配置如下:

HasMany(tc => tc.PreventCoverages).WithOptional(tc => tc.PreventedBy).HasForeignKey(tc=>PreventedById);