我有两张桌子
People Relation
------------- -----------------
Id (int) Id (int)
Name (string) ParentPeopleId (int)
ChildPeopleId (int)
我需要通过Relation表将所有人与union all联系起来。 关系表有两个外键。映射它们有一个问题。映射是一对多的。 人有很多关系,关系有一个人。
我将它们映射为:
HasRequired(r=> r.People).WithMany(p=>p.Relation).HasForeignKey(r=>r.ChildPeopleId);
那么,我该如何映射第二个外键?
答案 0 :(得分:1)
根据Relations
表中的每个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);
首先让我先提一个建议。我认为你的表Relation
没有扮演任何角色,你只有那些专栏。如果一个人只有父母,我会将你的模型改为:
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您要加载与Relation
相关的People
个实体,但您还要加载与每个People
相关的Relation
,同时People
所在的Relation
也是People
,因此,如果您的数据正确相关,则不需要执行最后一次选择var Peoplelist = MyDbContext.People.Include(p=>p.Relations).ToList();
导航在执行查询时将加载属性,因此,该查询应该是这样的:
newAccountButton