2.4.4 EF Core -- 关系
- 一对多
- 一对一
- 多对多
- 示例
一对多
// Dependent Entity 主表
public class Blog
{
// Principal Key 标识键/可能是主键或者备用键(唯一性约束)
public int BlogId { get; set; }
public string Url { get; set; }
// Collection navigation property 关联多个从表的属性集合(集合属性)
public List<Post> Posts { get; set; }
}
// Principal Entity 从表
public class Post
{
public int PostId { get; set; }
public string Title { get; set; }
public string Content { get; set; }
// Foreign Key 外键(指向主表中的 Principal Key)
// Inverse navigation property 反向导航属性
public int BlogId { get; set; }
// Inverse navigation property 反向导航属性
public Blog Blog { get; set; }
}
一对一
// Principal Entity 从表
public class Blog
{
public int BlogId { get; set; }
public string Url { get; set; }
public List<Post> Posts { get; set; }
}
// Dependent Entity 主表
public class Post
{
public int PostId { get; set; }
public string Title { get; set; }
public string Content { get; set; }
// Reference navigation property 一对一时指向另外一张表(引用属性)
public Blog Blog { get; set; }
}
多对多
public class Post
{
public int PostId { get; set; }
public string Title { get; set; }
public string Content { get; set; }
public ICollection<Tag> Tags { get; set; }
}
public class Tag
{
public string TagId { get; set; }
public ICollection<Post> Posts { get; set; }
}
示例
一对多
一个 Project 对应多个 ProjectGroup
在 Project 实体中添加 ProjectGroup 列表
public List<ProjectGroup> Groups { get; set; }
迁移
dotnet ef migrations add ProjectGroupCollectionProperty
生成集合属性 ProjectGroupCollectionProperty
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AlterColumn<string>(
name: "ProjectId",
table: "ProjectGroups",
nullable: true,
oldClrType: typeof(string),
oldType: "longtext CHARACTER SET utf8mb4",
oldNullable: true);
migrationBuilder.CreateIndex(
name: "IX_ProjectGroups_ProjectId",
table: "ProjectGroups",
column: "ProjectId");
migrationBuilder.AddForeignKey(
name: "FK_ProjectGroups_Projects_ProjectId",
table: "ProjectGroups",
column: "ProjectId",
principalTable: "Projects",
principalColumn: "Id",
onDelete: ReferentialAction.Restrict);
}
手动配置
class MyContext : DbContext
{
public DbSet<Blog> Blogs { get; set; }
public DbSet<Post> Posts { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
// 先在从表上建立一对一的关系,再从主表上建立一对多的关系
modelBuilder.Entity<Post>()
.HasOne(p => p.Blog)
.WithMany(b => b.Posts);
}
}
public class Blog
{
public int BlogId { get; set; }
public string Url { get; set; }
public List<Post> Posts { get; set; }
}
public class Post
{
public int PostId { get; set; }
public string Title { get; set; }
public string Content { get; set; }
public Blog Blog { get; set; }
}
LighterDbContext
// 一对一
modelBuilder.Entity<Project.ProjectGroup>().HasOne<Project.Project>(g => g.Project);
// 一对多
modelBuilder.Entity<Project.ProjectGroup>().HasOne<Project.Project>(g => g.Project).WithMany(p => p.Groups);
多对多
为 Project 和 Subject 建立中间表 SubjectProject
public class Project : Entity
{
public string Title { get; set; }
public DateTime StartDate { get; set; }
public DateTime EndDate { get; set; }
public string SupervisorId { get; set; }
public string PlanId { get; set; }
public List<ProjectGroup> Groups { get; set; }
public List<SubjectProject> SubjectProjects { get; set; }
}
public class Subject : Entity
{
public string Title { get; set; }
public string Content { get; set; }
public List<SubjectProject> SubjectProjects { get; set; }
}
public class SubjectProject : Entity
{
public string ProjcetId { get; set; }
public Project Project { get; set; }
public string SubjectId { get; set; }
public Subject Subject { get; set; }
}
配置多对多关系
LighterDbContext
// 多对多(两组一对多)
modelBuilder.Entity<Project.SubjectProject>()
.HasOne<Project.Project>(s => s.Project)
.WithMany(p => p.SubjectProjects)
.HasForeignKey(s => s.ProjcetId);
modelBuilder.Entity<Project.SubjectProject>()
.HasOne<Project.Subject>(s => s.Subject)
.WithMany(p => p.SubjectProjects)
.HasForeignKey(s => s.SubjectId);
迁移
dotnet ef migrations add SubjectProjectManyToManyRelation
SubjectProjectManyToManyRelation
table.ForeignKey(
name: "FK_SubjectProject_Projects_ProjcetId",
column: x => x.ProjcetId,
principalTable: "Projects",
principalColumn: "Id",
onDelete: ReferentialAction.Restrict);
table.ForeignKey(
name: "FK_SubjectProject_Subject_SubjectId",
column: x => x.SubjectId,
principalTable: "Subject",
principalColumn: "Id",
onDelete: ReferentialAction.Restrict);
中间表创建了两个外键,形成多对多
EF Core 5.0 多对多实现
public class Post
{
public int PostId { get; set; }
public string Title { get; set; }
public string Content { get; set; }
public ICollection<Tag> Tags { get; set; }
}
public class Tag
{
public string TagId { get; set; }
public ICollection<Post> Posts { get; set; }
}
迁移的时候会自动生成中间表
联接实体类型配置 HasMany
modelBuilder
.Entity<Post>()
.HasMany(p => p.Tags)
.WithMany(p => p.Posts)
.UsingEntity(j => j.ToTable("PostTags"));
GitHub源码链接:
https://github.com/MINGSON666/Personal-Learning-Library/tree/main/ArchitectTrainingCamp/LighterApi