C# 为什么EF代码首先生成一个无关的外键列?

C# 为什么EF代码首先生成一个无关的外键列?,c#,database,entity-framework,ef-code-first,C#,Database,Entity Framework,Ef Code First,我首先使用实体框架代码自动创建数据库模式,其中一个实体如下所示: public class AssessmentsCaseStudies { #region Persisted fields [Required] [Key, Column(Order=0)] [ForeignKey("Assessment")] public int AssessmentId { get; set; } [Required] [Key, Column(Or

我首先使用实体框架代码自动创建数据库模式,其中一个实体如下所示:

public class AssessmentsCaseStudies {
    #region Persisted fields
    [Required]
    [Key, Column(Order=0)]
    [ForeignKey("Assessment")]
    public int AssessmentId { get; set; }

    [Required]
    [Key, Column(Order=1)]
    [ForeignKey("CaseStudy")]
    public int CaseStudyId { get; set; }

    [Required]
    public int Score { get; set; }

    [ForeignKey("Follows")]
    public int? FollowsCaseStudyId { get; set; }
    #endregion

    #region Navigation properties
    public virtual Assessment Assessment { get; set; }
    public virtual CaseStudy CaseStudy { get; set; }
    public virtual CaseStudy Follows { get; set; }
    #endregion
}
EF自动生成我的数据库时,会生成一个包含以下列的表:

AssessmentId (PK, FK, int, not null)
CaseStudyId (PK, FK, int, not null)
Score (int, not null)
FollowsCaseStudyId (FK, int, null)
CaseStudy_CaseStudyId (FK, int, null)

除了
CaseStudy\u CaseStudyId
列之外,这一切都很好。为什么会产生这种情况?这是干什么用的?我怎样才能阻止它的生成?我怀疑EF不能再自动将
CaseStudy
ICollection
CaseStudyId
列匹配,因此,它创建了自己的列,将这两个导航属性链接在一起。

因为在
评估评估评估研究
实体中有两个
类型的
案例研究
导航属性,而在
案例研究
实体中有一个
评估评估评估研究
集合,EF无法决定是哪一个此集合引用的两个
案例研究中的
导航属性。两者都是可能的,并且这两个选项都会产生一个有效但不同的实体模型和数据库模式

在这种模棱两可的情况下,EF惯例是创建实际的三个关系,即
案例研究
中的集合不引用两个
案例研究
导航属性中的任何一个,但在
评估研究
中有第三个端点(但不公开和“不可见”)。这第三个关系是您在数据库中看到的第三个外键的原因—带下划线的外键。(下划线始终是通过映射约定而不是通过显式配置或数据注释发生事情的强烈指示。)

要解决问题并覆盖约定,您可以应用
[InverseProperty]
属性,从而指定
案例研究
导航属性
AssessmentsCaseStudies
集合所属:

[InverseProperty("AssessmentsCaseStudies")] // the collection in CaseStudy entity
public virtual CaseStudy CaseStudy { get; set; }
您还可以(或者,您不需要两者都使用)将属性放在集合端:

[InverseProperty("CaseStudy")] // the CaseStudy property in AssessmentsCaseStudies entity
public virtual ICollection<AssessmentsCaseStudies> AssessmentsCaseStudies { get; set; }
[InverseProperty(“案例研究”)]//评估案例研究实体中的案例研究属性
公共虚拟ICollection assessmentsCasStudies{get;set;}

出于某种原因,Slauma的
反向属性建议不起作用。我所做的工作是通过数据库上下文的
OnModelCreating
方法中的Fluent API指定
案例研究
导航属性和
案例研究
实体之间的关系:

modelBuilder.Entity<AssessmentsCaseStudies>()
    .HasRequired(acs => acs.CaseStudy)
    .WithMany(cs => cs.AssessmentsCaseStudies)
    .HasForeignKey(acs => acs.CaseStudyId)
    .WillCascadeOnDelete(false);

modelBuilder.Entity<AssessmentsCaseStudies>()
    .HasOptional(acs => acs.Follows)
    .WithMany()  // No reverse navigation property
    .HasForeignKey(acs => acs.FollowsCaseStudy)
    .WillCascadeOnDelete(false);
modelBuilder.Entity()
.HasRequired(acs=>acs.案例研究)
.有许多(cs=>cs.评估研究)
.HasForeignKey(acs=>acs.CaseStudyId)
.WillCascadeOnDelete(假);
modelBuilder.Entity()
.has可选(acs=>acs.Follows)
.WithMany()//无反向导航属性
.HasForeignKey(acs=>acs.followsCaseStudio)
.WillCascadeOnDelete(假);

添加后,当我添加迁移时生成的迁移代码不再尝试添加
CaseStudy\u CaseStudyId
列,我只添加了
FollowsCaseStudyId
列,并添加了相应的外键关系。

对于任何登陆此处寻找解决方案的人,如果您已经尝试了前面的答案,但仍然得到了一个额外的外键列,请查找您可能在POCO类下定义的、不打算映射到DB字段的任何属性。即使它们包含代码块,就像复杂的get访问器一样,实体框架也会尝试以某种方式将它们映射到数据库。如果属性返回实体,这可能会导致额外的外键列。为了安全起见,要么用
[NotMapped]
属性装饰这些属性,要么将它们转换为方法。

我真的不明白这个问题的公认答案。我在
评估研究
中正好有两个
案例研究
参考资料,因此我没有真正的多对多关系,也不明白为什么我需要一个连接表。不过,我在
案例研究
中确实有
公共虚拟ICollection评估研究{get;set;}
,所以我想说,ICollection应该与
案例研究ID
FK相关,而不是
FollowsCaseStudyId
FK。好的,我认为它可能包含有用的信息。您是否可以尝试创建一个精简的示例,例如,仅使用
评估
案例研究
评估案例研究
实体,每个实体仅包含一个
ID
字段,而
评估案例研究
包含一个
评估ID
和一个
案例研究ID
字段?这个问题还会发生吗?我不认为这个问题应该结束,因为对“被骗”问题的公认答案不能很好地解释问题,我想要一个更好的答案。请投票重新打开。您是否因
InverseProperty
属性而出现异常,或者您是否仍有第三个FK?这本应该奏效的。它与Fluent映射的作用相同-只有一个例外:该属性没有为第一个关系禁用级联删除(因为第二个级联删除是可选关系,所以默认情况下处于禁用状态)。它仍然创建了第三个FK。我正在处理类似的问题-我尝试了你的建议,但遇到了一个异常。如果你有时间: