ef core 2.1 多对多
ef core 2.1 Many To Many
我有 4 个表,我试图在 EF Core 2.1 中创建它们的关系
一部作品中有一个或多个角色。例如一部作品 "Hamilton" 有一个人担任导演,
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 Class:
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);
}
}
我的方向是否正确?
是的,只需验证数据库架构。
因为如果不正确,EF 将创建具有不同体系结构的数据库。
设计还可以。但是流畅的配置不是。 EF Core 不允许在 fluent API 中使用嵌套属性,因此您的 HasKey
和 HasForeignKey
方法使用将导致运行时异常。
由于您的模型符合 EF Core 约定,并且所有关系都在两端使用导航属性进行描述,因此 EF Core 将能够自动确定几乎所有内容 w/o 任何流畅的配置,除了连接实体组合首要的关键。这是唯一需要流畅配置的。
虽然可以仅使用阴影属性配置复合 PK(了解 FK 属性 命名的 EF Core 约定,例如 public Person Person
-> int PersonId
):
modelBuilder.Entity<ProductionPersonRole>()
.HasKey("ProductionId", "PersonId", "RoleId");
我建议向连接实体添加显式 FK 属性:
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 });
它不仅避免了硬编码字符串的使用,而且在 inserting/deleting 断开连接的情况下链接时也非常有用。
我有 4 个表,我试图在 EF Core 2.1 中创建它们的关系
一部作品中有一个或多个角色。例如一部作品 "Hamilton" 有一个人担任导演,
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 Class:
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);
}
}
我的方向是否正确?
是的,只需验证数据库架构。 因为如果不正确,EF 将创建具有不同体系结构的数据库。
设计还可以。但是流畅的配置不是。 EF Core 不允许在 fluent API 中使用嵌套属性,因此您的 HasKey
和 HasForeignKey
方法使用将导致运行时异常。
由于您的模型符合 EF Core 约定,并且所有关系都在两端使用导航属性进行描述,因此 EF Core 将能够自动确定几乎所有内容 w/o 任何流畅的配置,除了连接实体组合首要的关键。这是唯一需要流畅配置的。
虽然可以仅使用阴影属性配置复合 PK(了解 FK 属性 命名的 EF Core 约定,例如 public Person Person
-> int PersonId
):
modelBuilder.Entity<ProductionPersonRole>()
.HasKey("ProductionId", "PersonId", "RoleId");
我建议向连接实体添加显式 FK 属性:
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 });
它不仅避免了硬编码字符串的使用,而且在 inserting/deleting 断开连接的情况下链接时也非常有用。