.NET 云原生架构师训练营(模块二 基础巩固 EF Core 关系)--学习笔记
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/MingsonZheng/ArchitectTrainingCamp/tree/main/LighterApi
课程链接
https://appsqsyiqlk5791.h5.xiaoeknow.com/v1/course/video/v_5f39bdb8e4b01187873136cf?type=2

本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。
欢迎转载、使用、重新发布,但务必保留文章署名 郑子铭 (包含链接: http://www.cnblogs.com/MingsonZheng/ ),不得用于商业目的,基于本文修改后的作品务必以相同的许可发布。
如有任何疑问,请与我联系 (MingsonZheng@outlook.com) 。
.NET 云原生架构师训练营(模块二 基础巩固 EF Core 关系)--学习笔记的更多相关文章
- .NET 云原生架构师训练营(权限系统 RGCA 开发任务)--学习笔记
目录 目标 模块拆分 OPM 开发任务 目标 基于上一讲的模块划分做一个任务拆解,根据任务拆解实现功能 模块拆分 模块划分已经完成了边界的划分,边界内外职责清晰 OPM 根据模块拆分画出 OPM(Ob ...
- .NET 云原生架构师训练营(权限系统 代码实现 ActionAccess)--学习笔记
目录 开发任务 代码实现 开发任务 DotNetNB.Security.Core:定义 core,models,Istore:实现 default memory store DotNetNB.Secu ...
- .NET 云原生架构师训练营(权限系统 代码实现 WebApplication)--学习笔记
目录 开发任务 代码实现 开发任务 DotNetNB.Security.Core:定义 core,models,Istore:实现 default memory store DotNetNB.WebA ...
- .NET 云原生架构师训练营(权限系统 系统演示 ActionAccess)--学习笔记
目录 模块拆分 环境配置 默认用户 ActionAccess 模块拆分 环境配置 mysql migration mysql docker pull mysql docker run -p 3306: ...
- .NET 云原生架构师训练营(权限系统 系统演示 EntityAccess)--学习笔记
目录 模块拆分 EntityAccess 模块拆分 EntityAccess 实体权限 属性权限 实体权限 创建 student https://localhost:7018/Student/dotn ...
- .NET 云原生架构师训练营(权限系统 代码实现 EntityAccess)--学习笔记
目录 开发任务 代码实现 开发任务 DotNetNB.Security.Core:定义 core,models,Istore:实现 default memory store DotNetNB.Secu ...
- .NET 云原生架构师训练营(权限系统 代码实现 Identity)--学习笔记
目录 开发任务 代码实现 开发任务 DotNetNB.Security.Core:定义 core,models,Istore:实现 default memory store DotNetNB.Secu ...
- .NET 云原生架构师训练营(模块一 架构师与云原生)--学习笔记
目录 什么是软件架构 软件架构的基本思路 单体向分布式演进.云原生.技术中台 1.1 什么是软件架构 1.1.1 什么是架构? Software architecture = {Elements, F ...
- .NET 云原生架构师训练营(建立系统观)--学习笔记
目录 目标 ASP .NET Core 什么是系统 什么是系统思维 系统分解 什么是复杂系统 作业 目标 通过整体定义去认识系统 通过分解去简化对系统的认识 ASP .NET Core ASP .NE ...
- .NET 云原生架构师训练营(权限系统 RGCA 架构设计)--学习笔记
目录 项目核心内容 实战目标 RGCA 四步架构法 项目核心内容 无代码埋点实现对所有 API Action 访问控制管理 对 EF Core 实体新增.删除.字段级读写控制管理 与 Identity ...
随机推荐
- [tslint] Identifier 'loggedIn' is never reassigned; use 'const' instead of 'let'. (prefer-const)
- 封装http并挂载到全局
https://www.bilibili.com/video/BV1BJ411W7pX?p=32 具体使用:https://blog.csdn.net/weixin_44763569/article/ ...
- 2024-01-20:用go语言,小扣在探索丛林的过程中,无意间发现了传说中“落寞的黄金之都“, 而在这片建筑废墟的地带中,小扣使用探测仪监测到了存在某种带有「祝福」效果的力场, 经过不断的勘测记录,
2024-01-20:用go语言,小扣在探索丛林的过程中,无意间发现了传说中"落寞的黄金之都", 而在这片建筑废墟的地带中,小扣使用探测仪监测到了存在某种带有「祝福」效果的力场, ...
- @EnableFeignClients注解源码解析
转载请注明出处: @EnableFeignClients 注解定义的源码 @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.TYPE}) ...
- JS - 兼容到 IE 8
使用 jQuery可以有效的兼容IE 浏览器 , 但jQuery从2.0开始不兼容IE8,最低支持IE9,所以需要引入更低的jQuery版本来兼容 <script type="text ...
- 使用JavaStream将List转为Map
有的时候博客内容会有变动,首发博客是最新的,其他博客地址可能会未同步,认准https://blog.zysicyj.top 首发博客地址 系列文章地址 使用Java Stream将List转换为Map ...
- [转帖]SCSI、ISCSI、iSER、NVMe、NVMe-oF、NVMe-oF over RDMA
在存储系统中,上层协议可以泛指"指令",也就是比如"读出从某某开始的多少长度的扇区",指令包含三大关键信息: (1)操作码:Opreation Code,或称为 ...
- [转帖]如何修改Bash Shell的提示符的格式和配色
https://zhuanlan.zhihu.com/p/348416919 我们大多数使用的shell提示符,显示用户名.主机名和当前所在目录.在本文将会介绍如何定制一个自己喜欢的Bash. 了解B ...
- [转帖]Linux开源存储漫谈(2)IO性能测试利器fio
fio(Flexible I/O Tester)正是非常常用的文件系统和磁盘 I/O 性能基准测试工具.提供了大量的可定制化选项,可以用来测试,裸盘.一个单独的分区或者文件系统在各种场景下的 I/O ...
- [转帖]【JVM】GC算法与垃圾收集器
引入 java 语言中一个显著的特点就是引入了java回收机制,是c++程序员最头疼的内存管理的问题迎刃而解,它使得java程序员在编写程序的时候不在考虑内存管理.由于有个垃圾回收机制,可以有效的防止 ...