代码之家  ›  专栏  ›  技术社区  ›  Rick Hodder

ef核心2.1多对多

  •  1
  • Rick Hodder  · 技术社区  · 7 年前

    我有4个表,我试图在efcore2.1中创建它们之间的关系

    一部作品有一个或多个角色。e、 g.一部名为“汉密尔顿”的作品有一个人担任导演,

    Production
    ProductionId     Name        
    ------------     -----------
    PR1               Hamilton
    
    Person
    PersonId         Name
    --------         -----------
    P1               Rick
    P2               Chris
    P3               Dan
    
    Role
    RoleId           Name
    ----------       -----------
    R1               Director
    R2               Choreographer
    R3               Actor
    
    ProductionRolePerson
    ProductionId    PersonId    RoleId
    ------------    --------    ------
    PR1             P1 (Rick)   R1 (Director)
    PR1             P2 (Chris)  R2 (Choreographer)
    PR1             P3 (Dan)    R3 (Actor)
    
    
    Production 
        | 1
        | *
    ProductionPersonRole
    | *             | *
    | 1             | 1
    Person         Role
    

    我想不出建立一对多关系的正确方法。

    以下是我开设的课程:

     public class Production 
        {
            public int ProductionId { get; set; }
            public List<ProductionPersonRole> Roles { get; set; }
        }
    
        public class Person 
        {
            public int PersonId { get; set; }
            public string FirstName { get; set; }
            public string LastName { get; set; }
    
            public ICollection<ProductionPersonRole> ProductionPersonRoles { get; set; }
        }
    
    public class Role
        {
            public int RoldId { get; set; }
            public string Name {get;set;}
            public ICollection<ProductionPersonRole> Jobs { get; set; }
        }
    
    public class ProductionPersonRole
        {
            public Production Production { get; set; }
            public Person Person { get; set; }
            public Role Role { get; set; }
        }
    

    以下是DbContext类:

        public class MyContext : DbContext
            {
                public DbSet<Production> Productions { get; set; }
                public DbSet<ProductionPersonRole> ProductionPersonRoles { get; set; }
                public DbSet<Role> Roles { get; set; }
                public DbSet<Person> Persons { get; set; }
    
                public MyContext(): base()
                {
    
                }
    
                public MyContext(DbContextOptions options): base(options)
                {
    
                }
    
                protected override void OnModelCreating(ModelBuilder modelBuilder)
                {
                    modelBuilder.Entity<ProductionPersonRole>()
                        .HasKey(ppr => new {ppr.Production.ProductionId, ppr.Person.PersonId, ppr.Role.RoldId});
    
                    modelBuilder.Entity<ProductionPersonRole>()
                        .HasOne(ppr => ppr.Production)
                        .WithMany(ppr => ppr.Roles)
                        .HasForeignKey(ppr => ppr.Production.ProductionId);
    
                    modelBuilder.Entity<ProductionPersonRole>()
                        .HasOne(ppr => ppr.Person)
                        .WithMany(ppr => ppr.ProductionPersonRoles)
                        .HasForeignKey(ppr => ppr.Person.PersonId);
    
                    modelBuilder.Entity<ProductionPersonRole>()
                        .HasOne(ppr => ppr.Role)
                        .WithMany(ppr => ppr.Jobs)
                        .HasForeignKey(ppr => ppr.Role.RoleId);
    
                    base.OnModelCreating(modelBuilder);
                }
    }
    

    我的方向正确吗?

    2 回复  |  直到 7 年前
        1
  •  1
  •   Ivan Stoev    7 年前

    设计还可以。但流畅的配置并非如此。EF Core不允许在fluent API中使用嵌套属性,因此 HasKey HasForeignKey 方法的使用将导致运行时异常。

    要求

    虽然可以只使用阴影属性配置复合PK(例如,了解FK属性命名的EF核心约定) public Person Person int PersonId ):

    modelBuilder.Entity<ProductionPersonRole>()
         .HasKey("ProductionId", "PersonId", "RoleId");
    

    public class ProductionPersonRole
    {
        public int ProductionId { get; set; }
        public int PersonId { get; set; }
        public int RoleId { get; set; }
        public Production Production { get; set; }
        public Person Person { get; set; }
        public Role Role { get; set; }
    }
    

    而是使用以下配置:

    modelBuilder.Entity<ProductionPersonRole>()
         .HasKey(ppr => new { ppr.ProductionId, ppr.PersonId, ppr.RoleId });
    

    它不仅避免使用硬编码字符串,而且在断开连接的情况下插入/删除链接时也非常有用。

        2
  •  1
  •   Inline Instructions.    7 年前

    是的,只需验证数据库架构。 因为如果不正确,EF将创建具有不同体系结构的DB。