我有三个相关的实体,这里是使用Fluent API声明的结构和关系
参加许多人(实际上是一群人)的活动,因此有可能通过GroupID
收集所有人。那怎么做呢?
public class Event
{
public int EventID { get; set; }
public string DocID { get; set; }
public string GroupID { get; set; }
public virtual Person Person { get; set; }
public virtual Group Group { get; set; }
public virtual ICollection<Person> GroupPerson {get; set}
}
人实体,这里我有关于人的所有信息,如姓名,姓氏,生日...
public class Person
{
public string PersonID { get; set; }
public string PersonName { get; set; }
public string PersonSurName { get; set; }
public string PersonCode { get; set; }
}
群组实体,这是有关群组的信息
public class Group
{
public string GroupID { get; set; }
public string GroupName { get; set; }
public virtual ICollection<Event> EventGroup { get; set; }
}
现在我使用Fluent API描述关系。主键首先是:
modelBuilder.Entity<Event>().HasKey(e => e.EventID);
modelBuilder.Entity<Person>().HasKey(e => e.PersonID);
modelBuilder.Entity<Group>().HasKey(e => e.GroupID);
在这里,我将有与事件有关的人
modelBuilder.Entity<Event>()
.HasRequired(s => s.Person)
.WithMany()
.HasForeignKey(fk=> fk.PersonID);
这里我将有PersonGroup
modelBuilder.Entity<Group>()
.HasKey(e => e.GroupID)
.HasMany(e => e.EventGroup)
.WithOptional()
.HasForeignKey(f => f.GroupID);
我的问题是如何建立关系以获得群组中的人员列表?
PersonGroup
类型为Event
,我需要Person => ICollection<Person> GroupPerson
类中的人员列表:Event
。
答案 0 :(得分:1)
鉴于你的关系是这样的:
也就是说,您的关系事件 - 群组是一对多的,您的关系群组 - 人物是多对多的(我假设同一个人可以在多个群组中)。事件和人之间没有直接的关系,但是传递关系事件 - &gt;组 - &gt;人
然后可以这样建模:
public class Event
{
public int EventID { get; set; }
public string DocID { get; set; }
public string GroupID { get; set; }
public virtual Group Group { get; set; }
public virtual ICollection<Person> People { get { return Group.People; } }
}
public class Person
{
public string PersonID { get; set; }
public string PersonName { get; set; }
public string PersonSurName { get; set; }
public string PersonCode { get; set; }
}
public class Group
{
public string GroupID { get; set; }
public string GroupName { get; set; }
public virtual ICollection<Event> Events { get; set; }
public virtual ICollection<Person> People { get; set; }
}
在DbContext
中使用这些DbSet:
public DbSet<Person> People { get; set; }
public DbSet<Group> Groups { get; set; }
public DbSet<Event> Events { get; set; }
这个EF配置:
modelBuilder.Entity<Event>()
.HasKey(e => e.EventID)
.Ignore(e => e.People)
.HasRequired(e => e.Group)
.WithMany(g => g.Events);
modelBuilder.Entity<Group>()
.HasKey(g => g.GroupID)
.HasMany(g => g.People)
.WithMany();
modelBuilder.Entity<Person>()
.HasKey(p => p.PersonID);
请注意,Ignore()
有明确的Event.People
。这是因为Event和Person之间的关系是可传递的,您不需要为数据库添加额外的列。如果您不明白为什么,请尝试注释掉Ignore()
行并重新生成迁移,并看到在“人员”表格中生成了一个额外的事件ID列(此列不会生成很有道理)。
因此,People
中的Events
属性未由EF填充,您必须自己完成:
public virtual ICollection<Person> People { get { return Group.People; } }
要将人员添加到活动中,您应该使用组导航属性,如下所示:
public class Event
{
...
public void AddPerson(Person p)
{
this.Group.People.Add(p);
}
}
使用此代码,迁移就像这样生成,包含四个表:Events
,Groups
,People
和额外的表PeopleGroups
,用于多对多人与群的关系。
public override void Up()
{
CreateTable(
"dbo.Events",
c => new
{
EventID = c.Int(nullable: false, identity: true),
DocID = c.String(),
GroupID = c.String(nullable: false, maxLength: 128),
})
.PrimaryKey(t => t.EventID)
.ForeignKey("dbo.Groups", t => t.GroupID, cascadeDelete: true)
.Index(t => t.GroupID);
CreateTable(
"dbo.Groups",
c => new
{
GroupID = c.String(nullable: false, maxLength: 128),
GroupName = c.String(),
})
.PrimaryKey(t => t.GroupID);
CreateTable(
"dbo.People",
c => new
{
PersonID = c.String(nullable: false, maxLength: 128),
PersonName = c.String(),
PersonSurName = c.String(),
PersonCode = c.String(),
})
.PrimaryKey(t => t.PersonID);
CreateTable(
"dbo.GroupPersons",
c => new
{
Group_GroupID = c.String(nullable: false, maxLength: 128),
Person_PersonID = c.String(nullable: false, maxLength: 128),
})
.PrimaryKey(t => new { t.Group_GroupID, t.Person_PersonID })
.ForeignKey("dbo.Groups", t => t.Group_GroupID, cascadeDelete: true)
.ForeignKey("dbo.People", t => t.Person_PersonID, cascadeDelete: true)
.Index(t => t.Group_GroupID)
.Index(t => t.Person_PersonID);
}
如果您不喜欢关系表GroupPersons
中列的名称,则可以添加.Map()
配置(但您不需要这样做,因为这个表格没有直接使用,没有模型实体,它在DbSet
中甚至没有DbContext
属性。