Entity Framework 多个外键指向同一个 table
Entity Framework multiple foreign keys to the same table
我有两个实体 DataTag 和 CalcDataTag:
public class CalcDataTag : BaseModel
{
[Column("CalcDataTagId")]
public override Guid ID { get; set; }
public Guid DataTagId { get; set; }
public DataTag DataTag { get; set; }
public Guid ChildDataTagId { get; set; }
public DataTag ChildDataTag { get; set; }
}
public class DataTag : BaseModel
{
[Column("DataTagId")]
public override Guid ID { get; set; }
public ICollection<CalcDataTag> CalcDataTags { get; set; }
}
我这样设置上下文:
modelBuilder.Entity<DataTag>()
.HasMany<CalcDataTag>(x => x.CalcDataTags)
.WithRequired(x => x.ChildDataTag)
.HasForeignKey(x => x.ChildDataTagId);
modelBuilder.Entity<DataTag>()
.HasMany<CalcDataTag>(x => x.CalcDataTags)
.WithRequired(x => x.DataTag)
.HasForeignKey(x => x.DataTagId);
CalcDataTags 列表应该是一个 CalcDataTags 列表,其中 DataTagId 或 ChildDataTagId 等于 DataTag 的 ID,但是上下文的设置方式,底部设置覆盖顶部设置,我只得到一个列表CalcDataTags,其中 DataTagId 等于 DataTag 的 ID。如果我切换设置,那么我只会得到一个 CalcDataTags 列表,其中 ChildCalcDataTagId 等于 DataTag 的 ID。基本上我想要得到的是两个列表的联合。每个实体只有一个主键,没有复合键。
您的 DataTag
table 需要第二个 collection。没有其他办法解决它。 Entity Framework 越来越混乱,因为它只能将一个 one-to-many 关系映射到特定的 属性,而不是两个。您需要执行以下操作:
在DataTag
中:
public ICollection<CalcDataTag> CalcDataTags { get; set; }
public ICollection<CalcDataTag> ChildCalcDataTags { get; set; }
在你的modelBuilder
中:
modelBuilder.Entity<DataTag>()
.HasMany<CalcDataTag>(x => x.ChildCalcDataTags)
.WithRequired(x => x.ChildDataTag)
.HasForeignKey(x => x.ChildDataTagId);
modelBuilder.Entity<DataTag>()
.HasMany<CalcDataTag>(x => x.CalcDataTags)
.WithRequired(x => x.DataTag)
.HasForeignKey(x => x.DataTagId);
如果您希望能够同时抓取所有这些(就像您所做的那样),您可能需要考虑添加一个 [NotMapped]
属性 来抓取两个 collection 的并集,如下所示:
[NotMapped]
public ICollection<CalcDataTag> AllCalcDataTags
{
return CalcDataTags.Union(ChildCalcDataTags);
}
我有两个实体 DataTag 和 CalcDataTag:
public class CalcDataTag : BaseModel
{
[Column("CalcDataTagId")]
public override Guid ID { get; set; }
public Guid DataTagId { get; set; }
public DataTag DataTag { get; set; }
public Guid ChildDataTagId { get; set; }
public DataTag ChildDataTag { get; set; }
}
public class DataTag : BaseModel
{
[Column("DataTagId")]
public override Guid ID { get; set; }
public ICollection<CalcDataTag> CalcDataTags { get; set; }
}
我这样设置上下文:
modelBuilder.Entity<DataTag>()
.HasMany<CalcDataTag>(x => x.CalcDataTags)
.WithRequired(x => x.ChildDataTag)
.HasForeignKey(x => x.ChildDataTagId);
modelBuilder.Entity<DataTag>()
.HasMany<CalcDataTag>(x => x.CalcDataTags)
.WithRequired(x => x.DataTag)
.HasForeignKey(x => x.DataTagId);
CalcDataTags 列表应该是一个 CalcDataTags 列表,其中 DataTagId 或 ChildDataTagId 等于 DataTag 的 ID,但是上下文的设置方式,底部设置覆盖顶部设置,我只得到一个列表CalcDataTags,其中 DataTagId 等于 DataTag 的 ID。如果我切换设置,那么我只会得到一个 CalcDataTags 列表,其中 ChildCalcDataTagId 等于 DataTag 的 ID。基本上我想要得到的是两个列表的联合。每个实体只有一个主键,没有复合键。
您的 DataTag
table 需要第二个 collection。没有其他办法解决它。 Entity Framework 越来越混乱,因为它只能将一个 one-to-many 关系映射到特定的 属性,而不是两个。您需要执行以下操作:
在DataTag
中:
public ICollection<CalcDataTag> CalcDataTags { get; set; }
public ICollection<CalcDataTag> ChildCalcDataTags { get; set; }
在你的modelBuilder
中:
modelBuilder.Entity<DataTag>()
.HasMany<CalcDataTag>(x => x.ChildCalcDataTags)
.WithRequired(x => x.ChildDataTag)
.HasForeignKey(x => x.ChildDataTagId);
modelBuilder.Entity<DataTag>()
.HasMany<CalcDataTag>(x => x.CalcDataTags)
.WithRequired(x => x.DataTag)
.HasForeignKey(x => x.DataTagId);
如果您希望能够同时抓取所有这些(就像您所做的那样),您可能需要考虑添加一个 [NotMapped]
属性 来抓取两个 collection 的并集,如下所示:
[NotMapped]
public ICollection<CalcDataTag> AllCalcDataTags
{
return CalcDataTags.Union(ChildCalcDataTags);
}