杨中科老师视频
.NET 5教程,.Net Core 2021视频教程,杨中科主讲_哔哩哔哩_bilibili
一、EF Core一对多关系配置
1、所谓“关系数据库”
2、复习,数据库表之间的关系,“一对一” “一对多” “多对多”
多对多表关系通过第三方关系表,保持对应关系
3、三部曲:实体类中关系属性;Fluent API关系配置;使用关系操作
一对多,实体类
Article public List<Comment> comments {get;set;} = new List<Comment>();
List推荐默认给空集合
Comment public Article Article{get;set;}
套路:HasXXX(...).WithXXX(...) 有XXX,反之带有XXX
一对多:HasOne(...).WithMany(...)
一对一:HasOne(...).WithOne(...)
多对多:HasMany(...).WithMany(...)
演示:建配置关系,插入数据
EF Core会“顺竿爬”,简化代码
二、
演示查询关联数据,把Article以及所有Comment查询出来
Article a=ctx.Article.Include(a=>a.Commentts).Single(a=>a.id==2);
Include:同时查询关联的对象
EF Core中目前没有一种方式让生成的sql采用那种join;
三、额外的外键字段,需求:只想获得ArticleId和Comment,不要Article其他字段
SQL优化,尽量不要select * 原则,采用Linq select 匿名类
在查询时,使用select可以省略写Include,但是SQL还是会join
步骤:
1、在实体类中显式声明一个外键属性
2、在关系配置中通过 HasForeignKey(c=>c.ArticleId) 指定这个属性为外键
3、除非必要,否则不用声明外键列,因为会引入重复
EF Core:大部分查询比绝大部分程序员写出来的SQL性能都要高,有少部分SQL语句性能可能不尽如人意,但是也影响不大,特殊的一些SQL语句可能影响性能瓶颈,咱们再需要特殊优化
四、EF Core 单向导航属性
导航属性:在自己类中可以访问其他类的属性,例如:Comments
双向导航属性的问题,基础表被多个其他表引用时麻烦
单向导航对应结构
HasOne<User>(u=>u.Requester).WithMany() WithMany不设置参数
选择
对于主从结构的“一对多”表关系,一般是声明双向导航属性,而对于其他的“一对多”表关系,如果表属于被很多表引用的基础表,则用单向导航属性,否则可以自由决定是否是双向导航属性;
五、关系配置在任何一方都可以 推荐配置在多的那一端
正反都一样 一对多,多对一
演示配置放在另一方配置中
HasOne<Article>(c=>c.Article).WithMany(a=>a.Comments)
同等于 HasMany<Commentt>(a=>a.Comments).WithOne(c=>c.Article)
推荐策略,考虑到有单向导航属性的可能,我们一般用HasOne().WithMany(),关系配置到多的那一端;
六、自引用的组织结构树 类似字典表结构,ParentId是本身表的Id
代码演示, 利用“顺竿爬”两种方式二选一
自己研究下,这个地方优点绕,测试一下代码,插入数据
递归查询数据
new String('.',3) 指定字符重复若干次 new String('\t',3) 三个制表符
七、一对一
必须显式的在其中一个实体类中声明一个外键属性(在一对多中必要时才声明外键属性,一般不声明)
bulider.HasOne<Delivery>(o=>o.Delivery).WithOne(d=>d.order)
.HasForeignKey<Delivery>(d=>d.orderId);
外键属性在Deliver类中,配置外键在OrderConfig类中,是否可以调换位置呢??可以,配置在哪边都行
可以不用“顺竿爬”都存起来,靠谱;
八、多对多 EF Core5.0开始,才正式支持多对多
数据库中需要中间表
builder.HasMany<Teacher>(s=>s.Teachers).WithMany(t=>t.Students)
.UsingEntity(j=>j.ToTable("T_Students_Teachers"));
UsingEntity 设置中间表表名
代码演示,总结
九、基于关系的复杂查询,性能调优
eg:查找评论中含有“微软”两个子的所有文字(文字和评论是双向导航属性)
1、var items = ctx.Articles.Where(a=>a.Comments.Any(c=>c.Message.Contains("微软")));
2、var items = ctx.Comments.where(c=>c.Message.Contains("微软")).Select(c=>c.TheArticle).Distinct(); Distinct 去重
两种实现方式生成的sql不一样,可以对比调优