代码之家  ›  专栏  ›  技术社区  ›  Songaila

EF 6使用Fluent API编码优先关系。如何设置第一个表和第三个表之间的关系或获取分组集合

  •  0
  • Songaila  · 技术社区  · 7 年前

    我有三个相关的实体,下面是使用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); 
    

     modelBuilder.Entity<Group>()
                   .HasKey(e => e.GroupID)
                   .HasMany(e => e.EventGroup)
                   .WithOptional()
                   .HasForeignKey(f => f.GroupID);
    

    我的问题是如何设置一个关系来获得组中的人员列表? PersonGroup 是一个 Event 类型和我需要人员列表类型: Person => ICollection<Person> GroupPerson 在里面

    1 回复  |  直到 7 年前
        1
  •  1
  •   Diana    7 年前

    考虑到你们的关系是这样的:

    • 一个事件正好有(与)一个组(必需)
    • 一个群体与许多人无关

    也就是说,你的关系事件组是一对多的,而你的关系组人是多对多的(我假设同一个人可以在多个组中)。事件和人之间没有直接关系,而是一种传递关系事件->组->人

    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 :

    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 这是因为事件和人物之间的关系是可传递的,因此不需要数据库中额外的列。如果你不明白为什么,试着评论一下 行并重新生成迁移,然后在People表中为事件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);
        }
    }
    

    通过这段代码,迁移是这样生成的,有四个表: 事件 , Groups 和额外的桌子 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 中的属性 数据库上下文