C# EF同一主键上的多个外键关系
我想使用EF6创建一个多对多关系,使用代码优先的方法。我的实体使用复合主键(处理多租户) 让我们举一个简单而经典的例子。我有两个实体C# EF同一主键上的多个外键关系,c#,entity-framework,entity-framework-6,C#,Entity Framework,Entity Framework 6,我想使用EF6创建一个多对多关系,使用代码优先的方法。我的实体使用复合主键(处理多租户) 让我们举一个简单而经典的例子。我有两个实体Project和Person,它们具有多对多关系: public class Person { [Key, Column(Order = 1),] public Int32 Id { get; set; } [Key, Column(Order = 2)] public int TenantId { get; set; } publi
Project
和Person
,它们具有多对多关系:
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
,如下所示:
上面我定义了一个Project
到ProjectPerson
的关系。请注意,公共类ProjectPerson
{
[键,列(顺序=1),]
公共Int32 Id{get;set;}
[键,列(顺序=2)]
[外键(“项目”)]
public int TenantId{get;set;}
[ForeignKey("Project")]
public int ProjectId { get; set; }
public DateTime AddedDate{ get; set; }
public virtual Project Project { get; set; }
}
TenantId
用作主键和外键的一部分
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; }
}
到目前为止,模型按预期工作。但是缺少Person
到ProjectPerson
的关系
我在ProjectPerson
类中添加了以下两行
[ForeignKey("Person")]
public int PersonId { get; set; }
public virtual Person Person { get; set; }
确实缺少到TenantId
的映射。我不知道如何定义它
更新
我找到了这个。但是我仍然不满意,因为有额外的TenantId(PersontenatID
)作为外键
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; }
}
使用fluent API为联接表中的两个FK重用
tentandi
列。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 } );
}
公共类人物
{
[键,列(顺序=0)]
public int TenantId{get;set;}
[键,列(顺序=1)]
公共int PersonId{get;set;}
公共字符串名称{get;set;}
公共虚拟ICollection项目人员{get;set;}
}
公共类项目
{
[键,列(顺序=0)]
public int TenantId{get;set;}
[键,列(顺序=1)]
公共int ProjectId{get;set;}
公共字符串名称{get;set;}
公共虚拟ICollection项目人员{get;set;}
}
公共类项目人员
{
[键,列(顺序=0)]
公共整数{get;set;}
[键,列(顺序=1)]
公共int ProjectId{get;set;}
[键,列(顺序=2)]
公共int PersonId{get;set;}
公共日期时间添加数据{get;set;}
公共虚拟项目{get;set;}
公共虚拟人{get;set;}
}
模型创建时受保护的覆盖无效(DbModelBuilder modelBuilder)
{
基于模型创建(modelBuilder);
modelBuilder.Entity()
.HasMany(pr=>pr.ProjectPeople)
.WithRequired(pp=>pp.项目)
.HasForeignKey(pp=>new{pp.tentandi,pp.ProjectId});
modelBuilder.Entity()
.HasMany(pe=>pe.ProjectPeople)
.WithRequired(pp=>pp.个人)
.HasForeignKey(pp=>new{pp.tentandi,pp.PersonId});
}
为什么您需要ProjectPerson中的TenancId映射,您已经在project表和person表中都有了映射?就ProjectPerson而言,TenantId是不相关的。它只是一个关联表,给定的租户只能查询其租约中的项目或人员,对吗?您不需要此TenancId成为其中的一部分如果你试图强制它,这个表将以一个3表连接结束。除了这个@rism之外,还有两个原因:1.没有ProjectPerson中的TenantId,我们无法在DBMS中创建外键关联。2.租户数据应该能够在数据库之间移动。也就是说,每个记录都应该是唯一的。我按照上的说明进行了操作,但得到了以下信息lowing error映射不足:外键必须映射到一些概念上参与外键关联的AssociationSet或EntitySet。
您是说您已经设置了密钥,以便TenantA可以拥有ID=1的个人,而TenantB也可以拥有ID=1的独特个人记录?完全正确。特别是在fol中低电平情况。映像租户和租户在DB X中,而租户在DB Y中。稍后租户在DB Y中移动