自我引用1到多个关系

时间:2015-02-05 09:20:06

标签: entity-framework entity-framework-4

我有以下实体:

 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与关系'TravelCoverageType_PreventCoverages'中Role'TravelCoverageType_PreventCoverages_Source'中的引用约束冲突。由于从属角色中的所有属性都是不可为空的,因此主要角色的多重性必须为“1”。

     

System.Data.Entity.Edm.EdmAssociationEnd :: Multiplicity在关系'TravelCoverageType_PreventCoverages'中的角色'TravelCoverageType_PreventCoverages_Target'中无效。由于“从属角色”是指关键属性,因此从属角色的多重性的上限必须为“1”。

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

这是怎么做到的?

2 个答案:

答案 0 :(得分:1)

是否必须使用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:很多)。尝试向该类添加一个新属性(就像我上面的Data Annotations示例所做的那样),然后将配置更改为:

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

答案 1 :(得分:0)

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

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