Entity Framework Code First 的半递归关联

Semi-recursive associations with Entity Framework Code First

我希望你能帮助我解决我遇到的一个小问题。

我有一个 entity framework Code First 设置,其中我有以下设置:

public class UserDetails{
   public int Id {get;set;}
   //... some other properties .. //

   //This represents the approval group the user is a member of.
   public virtual ApprovalGroup {get;set;}

   //This represents the approval groups that the user is resposible for approving
   public virual ICollection<ApprovalGroup> ApprovalGroups {get;set;}
}

public class ApprovalGroup
{
    public int Id {get;set;}
    public string Name {get;set;}

    public virtual UserDetails Approvee {get;set;}
    public virtual ICollection<UserDetails> Members {get;set;}
}

在我的数据库上下文中,我有以下内容:

modelBuilder.Entity<ApprovalGroup>().ToTable("ApprovalGroup")
   .HasKey(t=>t.Id)
   .HasRequired(t=>t.Approver);

modelBuilder.Entity<ApprovalGroup>().HasMany(t=>t.Members)
    .WithOptional().WillCascadeOnDelete(false);

因此批准组必须有一个批准者设置,但它可能没有成员(特别是在首次配置时)。

此代码是 运行,但是当我检查它创建的数据库时,批准组 table 中有一个名为 "UserDetails_Id" 的额外列。它被设置为外键,但它始终为空。

它创建的 table 的架构包含以下列:

Id, Name, UserDetails_Id, Approver_Id

我不知道为什么它会创建不必要的 table "UserDetails_Id",我希望它不要这样做,因为没有理由这样做。我怀疑我的 configuration/mapping 行为有问题,但我不知道是什么。

到目前为止,google 未能阐明我做错了什么,所以如果这里有人可以提供帮助,我们将不胜感激。

尼克

您遇到的问题是由于 improper/incomplete 关系映射以及 EF 默认约定。

我建议您始终单独配置关系,每个关系仅配置一次,并使用与导航和显式 FK 属性的 presence/absence 完全匹配的重载。

在这种特殊情况下,您有两个 one-to-many 双向(即两端都有导航属性)关系,没有明确的 FK 属性。所以正确的配置应该是这样的:

// Entities
modelBuilder.Entity<ApprovalGroup>()
   .ToTable("ApprovalGroup")
   .HasKey(t => t.Id);

modelBuilder.Entity<UserDetails>()
   .ToTable("UserDetails")
   .HasKey(t => t.Id);

// Relationships
modelBuilder.Entity<ApprovalGroup>()
   .HasRequired(t => t.Approver)
   .WithMany(t => t.ApprovalGroups);

modelBuilder.Entity<ApprovalGroup>()
   .HasMany(t => t.Members)
   .WithOptional(t => t.ApprovalGroup) // or whatever the name of the navigation property is (it's missing in the posted code)
   .WillCascadeOnDelete(false);