《ASP.NET Core技术内幕与项目实战》精简集-EFCore2.8:EFCore7的重磅更新-批量操作
本节内容,为补充内容,部分类型涉及5.1和5.2,P129-P134。主要NuGet包:
一、实体更改跟踪
EFCore默认采用“快照更改跟踪”,会对“通过DbContext上下文查询出来的所有实体对象”进行跟踪,首次跟踪时,EFCore会为每个实体创建快照。通过对比当前值和快照值,就可以确定实体的当前状态,当执行SaveChanges时,会根据实体的状态,进行相应的数据库操作,并且跟踪的实体与发送到数据库的更改保持同步。状态跟踪有以下5种可能:
- Added状态,SaveChanges时插入数据库
- Deleted状态,SaveChanges时从数据库删除
- Modified状态,SaveChanges时将修改更新到数据库
- Unchanged状态,值为发生改变,SaveChanges时忽略
- Detached状态,上下文未跟踪,SaveChanges时忽略
1、获取指定实体对象的跟踪信息
//ctx.Entry()方法,可获取指定对象的跟踪信息对象EntityEntry var books = ctx.Books.Take(3).ToArray(); var book1 = books[0]; book1.Title = "xyz"; EntityEntry entry1 = ctx.Entry(book1); Console.WriteLine(entry1.State); //结果为Modified Console.WriteLine(entry1.DebugView.LongView);//打印详细的跟踪信息 //DebugView.LongView打印的结果如下 ======================= Book {Id: 1} Modified Id: 1 PK Price: 25 Title: 'xyz' Modified Originally 'abc' =======================
2、禁用跟踪AsNoTracking
EFCore对实体进行更改跟踪,要建立快照,进行当前值和快照值的对比,是比较消耗资源的。如果只是查询数据,不会发生状态改变,可以通过“禁用跟踪”,提升查询性能。
//禁用跟踪 var books_Tracking = ctx.Books.AsNoTracking().Take(3).ToArray(); var book1 = books_Tracking[0]; book1.Title = "xyz"; var entry2 = ctx.Entry(book1); Console.WriteLine(entry2.State); //结果为Detached
3、直接修改和删除
EFCore进行修改和删除操作时,需要先查询出指定数据,然后再进行修改或删除,编译为SQL时,首先会执行SELECT语句,然后再执行UPDATE或者DELETE,需要两句SQL。如果执行SQL,我们可以直接执行【UPDATE T_Book SET Title="xyz" WHERE Id=1】,效率更高。利用状态跟踪机制,我们可以让EFCore像SQL一样,直接进行更新或删除操作,不需要先查询再修改或删除。
//直接更新实体 var book1 = new Book { Id = 1 }; book1.Title = "xyz"; var entry1 = ctx.Entry(book1); entry1.Property("Title").IsModified= true; Console.WriteLine(entry1.DebugView.LongView); ctx.SaveChanges(); //直接删除实体 var book2 = new Book{ Id = 1 }; ctx.Entry(book2).State = EntityState.Deleted; ctx.SaveChanges();
二、EFCore7的批量修改
由于涉及实体的状态跟踪,如果进行数据库的批量操作时,如批量更新、批量删除等,需要一条一条进行,等于删除100条记录,需要执行100次DELETE,效率非常低,所以EFCore的批量操作一直被吐槽。批量操作提案,已被提出多年,但EFCore7之前,一直处于讨论状态,讨论核心主要是状态跟踪的问题。EFCore7终于带来了批量更新和批量删除(批量新增依旧没有),批量操作时,实体的跟踪状态与数据库更改不会同步,也就是说批量更新或删除的实体,是没有状态跟踪的,所以,之前几年讨论是为了啥?!如果执行完批量更新或删除后,如果要使用这些数据,应该再重新查询一次,这样可以建立状态跟踪。
1、批量删除ExcuteDelete/ExcuteDeleteAsync
//批量删除指定条件 ctx.Books.Where(b=>b.Id <= 2).ExecuteDelete(); //删除所有 await ctx.Books.ExecuteDeleteAsync(); //注意,如果数据表有删除约束条件,应该在删除主体前,先删除依赖项
2、批量更新ExcuteUpdate/ExcuteUpdateAsync
//批量更新所有,只更新一个属性 //ctx.Books.ExecuteUpdate(b => b.SetProperty(b=>b.Price,b=>b.Price + 50)); //批量更新指定条件,更新多个属性 await ctx.Books.Where(b => b.Price >= 50).ExecuteUpdateAsync(b=>b .SetProperty(b=>b.Title,"SameName") .SetProperty(b=>b.Price,b=>b.Price - 50) );
特别说明:
1、本系列内容主要基于杨中科老师的书籍《ASP.NET Core技术内幕与项目实战》及配套的B站视频视频教程,同时会增加极少部分的小知识点
2、本系列教程主要目的是提炼知识点,追求快准狠,以求快速复习,如果说书籍学习的效率是视频的2倍,那么“简读系列”应该做到再快3-5倍
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!