Entity Framework 映射。多个外键
Entity Framework Mapping. Multiple Foreign keys
我有两个table
People Relation
------------- -----------------
Id (int) Id (int)
Name (string) ParentPeopleId (int)
ChildPeopleId (int)
我需要通过 Relation table 和 union all 获取所有人。
关系 table 有两个外键。映射它们存在一个问题。映射是一对多的。 人物有很多关系,关系有一个人物。
我把它们映射成这样:
HasRequired(r=> r.People).WithMany(p=>p.Relation).HasForeignKey(r=>r.ChildPeopleId);
那么,如何映射第二个外键?
对于 Relations
table 中的每个 FK 列,您的 Relation
实体中应该有一个导航 属性(这不是强制性的,但强制性的是在关系中涉及的实体之间至少有一个导航属性)。在这种情况下,您在 People
和 Relations
之间有两个关系,导航 属性 表示关系中的一端。你的模型可能是这样的:
public class Relation
{
public int Id {get;set;}
public int ParentPeopleId {get;set;}
public int ChildPeopleId {get;set;}
public virtual People ParentPeople {get;set;}
public virtual People ChildPeople {get;set;}
}
public class People
{
public int Id {get;set;}
public string Name {get;set;}
public virtual ICollection<Relation> ParentRelations {get;set;}
public virtual ICollection<Relation> ChildRelations {get;set;}
}
Fluent Api 配置如下:
HasRequired(r=> r.ParentPeople ).WithMany(p=>p.ParentRelations ).HasForeignKey(r=>r.ParentPeopleId);
HasRequired(r=> r.ChildPeople).WithMany(p=>p.ChildRelations ).HasForeignKey(r=>r.ChildPeopleId );
现在,如果您不想在 People
实体中使用其中一个集合导航属性,则可以创建单向关系。例如,如果您不想要 ParenRelations
导航 属性,您可以按如下方式配置该关系:
HasRequired(r=> r.ParentPeople).WithMany().HasForeignKey(r=>r.ParentPeopleId);
更新
让我先从一个建议开始。我觉得你的 table Relation
没有发挥任何作用,因为你只有那些专栏。如果一个人只有 parent,我会将您的模型更改为以下内容:
public class People
{
public int Id {get;set;}
public string Name {get;set;}
public int ParentId {get;set;}
public virtual People Parent {get;set;}
public virtual ICollection<People> Children {get;set;}
}
你的关系配置为:
HasOptional(r=> r.Parent).WithMany(p=>p.Children).HasForeignKey(r=>r.ParentId);
现在回到您的 current model,EF 将您的 ChildPeopleId
属性 视为一个简单的标量列,它不知道它是一个 FK 列,这就是我上面建议的方式映射两个关系而不是一个关系。
另一件事,下面一行
var Peoplelist = MyDbContext.People.Include(p=>p.Relations.Select(r=>r.People)).ToList();
您告诉 EF 您想要加载与 People
相关的 Relation
个实体,而且您还想加载与每个 Relation
相关的 People
],这与 Relation
的来源相同 People
,因此,如果您的数据正确关联,则无需执行最后一个 select,即People
导航 属性 将在您执行查询时加载,因此,该查询应该是这样的:
var Peoplelist = MyDbContext.People.Include(p=>p.Relations).ToList();
我有两个table
People Relation
------------- -----------------
Id (int) Id (int)
Name (string) ParentPeopleId (int)
ChildPeopleId (int)
我需要通过 Relation table 和 union all 获取所有人。 关系 table 有两个外键。映射它们存在一个问题。映射是一对多的。 人物有很多关系,关系有一个人物。
我把它们映射成这样:
HasRequired(r=> r.People).WithMany(p=>p.Relation).HasForeignKey(r=>r.ChildPeopleId);
那么,如何映射第二个外键?
对于 Relations
table 中的每个 FK 列,您的 Relation
实体中应该有一个导航 属性(这不是强制性的,但强制性的是在关系中涉及的实体之间至少有一个导航属性)。在这种情况下,您在 People
和 Relations
之间有两个关系,导航 属性 表示关系中的一端。你的模型可能是这样的:
public class Relation
{
public int Id {get;set;}
public int ParentPeopleId {get;set;}
public int ChildPeopleId {get;set;}
public virtual People ParentPeople {get;set;}
public virtual People ChildPeople {get;set;}
}
public class People
{
public int Id {get;set;}
public string Name {get;set;}
public virtual ICollection<Relation> ParentRelations {get;set;}
public virtual ICollection<Relation> ChildRelations {get;set;}
}
Fluent Api 配置如下:
HasRequired(r=> r.ParentPeople ).WithMany(p=>p.ParentRelations ).HasForeignKey(r=>r.ParentPeopleId);
HasRequired(r=> r.ChildPeople).WithMany(p=>p.ChildRelations ).HasForeignKey(r=>r.ChildPeopleId );
现在,如果您不想在 People
实体中使用其中一个集合导航属性,则可以创建单向关系。例如,如果您不想要 ParenRelations
导航 属性,您可以按如下方式配置该关系:
HasRequired(r=> r.ParentPeople).WithMany().HasForeignKey(r=>r.ParentPeopleId);
更新
让我先从一个建议开始。我觉得你的 table Relation
没有发挥任何作用,因为你只有那些专栏。如果一个人只有 parent,我会将您的模型更改为以下内容:
public class People
{
public int Id {get;set;}
public string Name {get;set;}
public int ParentId {get;set;}
public virtual People Parent {get;set;}
public virtual ICollection<People> Children {get;set;}
}
你的关系配置为:
HasOptional(r=> r.Parent).WithMany(p=>p.Children).HasForeignKey(r=>r.ParentId);
现在回到您的 current model,EF 将您的 ChildPeopleId
属性 视为一个简单的标量列,它不知道它是一个 FK 列,这就是我上面建议的方式映射两个关系而不是一个关系。
另一件事,下面一行
var Peoplelist = MyDbContext.People.Include(p=>p.Relations.Select(r=>r.People)).ToList();
您告诉 EF 您想要加载与 People
相关的 Relation
个实体,而且您还想加载与每个 Relation
相关的 People
],这与 Relation
的来源相同 People
,因此,如果您的数据正确关联,则无需执行最后一个 select,即People
导航 属性 将在您执行查询时加载,因此,该查询应该是这样的:
var Peoplelist = MyDbContext.People.Include(p=>p.Relations).ToList();