与实体框架代码优先的半递归关联

时间:2017-05-18 17:03:35

标签: c# entity-framework entity-framework-6 code-first

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

我有一个实体框架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;}
}

在我的db上下文中,我有以下内容:

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

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

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

此代码正在运行,但是当我检查它创建的数据库时,批准组表中有一个额外的列,称为&#34; UserDetails_Id&#34;。它被设置为外键,但它始终为null。

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

Id, Name, UserDetails_Id, Approver_Id

我不知道为什么要创建不必要的表&#34; UserDetails_Id&#34;我不喜欢它,因为没有理由。我怀疑我的配置/映射行为有问题,但我无法弄清楚它是什么。

到目前为止,谷歌未能揭示我做错了什么,所以如果有人在这里可以提供帮助,我将不胜感激。

的Nik

1 个答案:

答案 0 :(得分:2)

您遇到的问题是由于不正确/不完整的关系映射,以及EF默认约定。

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

在这种特殊情况下,您有两个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);