【问题标题】:EF multiple foreign key relationship on same primary key同一主键上的EF多个外键关系
【发布时间】:2015-07-16 12:18:36
【问题描述】:

我想使用 EF 6 使用代码优先方法创建多对多关系。我的实体使用复合主键(处理多租户)。

让我们举一个简单而经典的例子。我有两个实体ProjectPerson,它们具有多对多关系:

public class Person
{
   [Key, Column(Order = 1),]
   public Int32 Id { get; set; } 
   [Key, Column(Order = 2)]
   public int TenantId { get; set; }
   public string Name { get; set; }
}

public class Project
{
   [Key, Column(Order = 1),]
   public Int32 Id { get; set; } 
   [Key, Column(Order = 2)]
   public int TenantId { get; set; }
   Public string Name { get; set; }
}

我也有一个像这样的连接表ProjectPerson

上面我已经定义了ProjectProjectPerson 的关系。请注意,公共类 ProjectPerson { [键,列(顺序 = 1),] 公共 Int32 Id { 获取;放; } [键,列(顺序 = 2)] [外键(“项目”)] 公共 int TenantId { 获取;放; }

   [ForeignKey("Project")]
   public int ProjectId { get; set; }

   public DateTime AddedDate{ get; set; }

   public virtual Project Project { get; set; }
}

TenantId 用作主键和外键的一部分。

到目前为止,该模型按预期工作。但是缺少PersonProjectPerson 的关系。

我在ProjectPerson 类中添加了以下两行

  [ForeignKey("Person")]
  public int PersonId { get; set; }

  public virtual Person Person { get; set; }

缺少到TenantId 的绝对映射。不知道怎么定义

更新

我找到了这个。但我仍然不满意,因为有额外的 TenantId (PersonTenantId) 作为外键。

 public class ProjectPerson
 {
   [Key, Column(Order = 1),]
   public Int32 Id { get; set; } 
   [Key, Column(Order = 2)]
   [ForeignKey("Project")]
   public int TenantId { get; set; }

   [ForeignKey("Project")]
   public int ProjectId { get; set; }

   [ForeignKey("Person")]
   public int PersonId { get; set; }
   [ForeignKey("Person")]
   public int PersonTenantId { get; set; } // duplicate 


   public DateTime AddedDate{ get; set; }

   public virtual Project Project { get; set; }
   public virtual Person Person { get; set; }

}

【问题讨论】:

  • 为什么在 ProjectPerson 中需要 TenantId 映射,您已经在 project 和 person 表中都有映射?就 ProjectPerson 而言,TenantID 无关紧要。它只是一个关联表,给定的租户只能查询其租户中的项目或人员,对吗?您不需要此 TenancyID 成为此表的一部分,如果您尝试强制它,最终会得到 3 个表连接。除此之外,看看这个febdev.wordpress.com/2013/01/30/…
  • @rism 两个原因: 1. ProjectPerson 中没有 TenantId,我们无法在 DBMS 中创建外键关联。 2. 租户数据应该能够在数据库之间移动。即每条记录都应该是唯一的。
  • 我按照febdev.wordpress.com/2013/01/30/… 的说明进行操作,但出现以下错误Insufficient mapping: Foreign key must be mapped to some AssociationSet or EntitySets participating in a foreign key association on the conceptual side.
  • 您是说您已经设置了密钥,以便租户A 可以拥有 ID = 1 的人员,而租户B 也可以拥有 ID = 1 的不同人员记录?
  • 完全可以。特别是在以下情况。成像 TenantA 和 TenantB 在 DB X 中,而 TenantC 在 DB Y 中。后来 TenantB 移动了 DB Y

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


【解决方案1】:

使用 fluent API 为联结表中的两个 FK 重用 TentantId 列。 ProjectId 也应该包含在联结表的 PK 中。请注意,我修改了复合主键列的顺序,将TenantId 作为第一列。

    public class Person
    {
        [Key, Column(Order = 0)]
        public int TenantId { get; set; }
        [Key, Column(Order = 1)]
        public int PersonId { get; set; }

        public string Name { get; set; }

        public virtual ICollection<ProjectPerson> ProjectPeople { get; set; }
    }

    public class Project
    {
        [Key, Column(Order = 0)]
        public int TenantId { get; set; }
        [Key, Column( Order = 1 )]
        public int ProjectId { get; set; }

        public string Name { get; set; }

        public virtual ICollection<ProjectPerson> ProjectPeople { get; set; }
    }

    public class ProjectPerson
    {
        [Key, Column( Order = 0 )]
        public int TentantId { get; set; }
        [Key, Column( Order = 1 )]
        public int ProjectId { get; set; }
        [Key, Column( Order = 2 )]
        public int PersonId { get; set; }

        public DateTime AddedDate { get; set; }

        public virtual Project Project { get; set; }
        public virtual Person Person { get; set; }
    }


    protected override void OnModelCreating( DbModelBuilder modelBuilder )
    {
        base.OnModelCreating( modelBuilder );

        modelBuilder.Entity<Project>()
            .HasMany(pr => pr.ProjectPeople )
            .WithRequired( pp => pp.Project )
            .HasForeignKey( pp => new { pp.TentantId, pp.ProjectId } );

        modelBuilder.Entity<Person>()
            .HasMany( pe => pe.ProjectPeople )
            .WithRequired( pp => pp.Person )
            .HasForeignKey( pp => new { pp.TentantId, pp.PersonId } );
    }

【讨论】:

    猜你喜欢
    • 2020-10-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-10-28
    • 2020-01-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多