mysql ef5 批量删除_Entity Framework Core 5中实现批量更新、删除

本文介绍了一个在Entity Framework Core 5中不需要预先加载数据而使用一句SQL语句批量更新、删除数据的开发包,并且分析了其实现原理,并且与其他实现方案做了比较。

一、背景

随着微软全面拥抱开源,.Net开源社区百花开放,涌现了非常多优秀的开源,ORM项目就有Dapper、SqlSugar、PetaPoco、FreeSQL等。作为微软官方提供的ORM框架,Entity Framework Core(以下简称EF Core)显然是被关注最多的。EF Core非常优秀而且功能丰富,但是EF Core有一个一直被人诟病的地方就是它并不能很好支持数据的批量更新和批量删除。在EF Core中批量更新和删除数据都要先把数据加载到内存中,然后再对数据操作,最后再SaveChanges,比如下面的代码用于把所有Id大于2或者AuthorName中含有”zack”的价格增加3:var books2 = ctx.Books.Where(b => b.Id > 2||b.AuthorName.Contains("zack"));

foreach(var b in books2)

{

b.Price = b.Price + 3;

}

ctx.SaveChanges();

让我们查看上面的程序幕后执行的SQL语句:e0fe54b2e11ae44d5c4e7ebaed58d1f4.png

可以看到,EF Core先把数据用Select查询出来,然后在内存中逐个修改,最后再把被修改对象每个都执行一次Update语句去更新。

再比如,如下的代码用于删除Price大于5元的记录:var books1 = ctx.Books.Where(b => b.Price > 5);

ctx.RemoveRange(books1);

ctx.SaveChanges();

让我们查看上面的程序运行幕后执行的SQL语句:

e12d68d8f88d3f23cfdd03d598d33b5d.png

可以看到,EF Core先把数据用Select查询出来,然后再对每条记录都执行Delete语句去删除。

很显然,如果批量更新或者删除的数据量比较大,这样的操作性能是非常低的。

因此,我们需要一种在EF Core中使用一条SQL语句就高性能地删除或者更新数据的方法。

二、为什么微软不提供这样的方法

尽管用户的要求强烈,但是微软一直没有提供高效的批量删除和更新的方式。在EF Core Github的issue中 [1],微软给出的理由是:这样做会导致EF Core的对象状态跟踪混乱,比如对于同一个DbContext,如果用批量删除的方法删除了数据,那么在被删除之前查询出来的数据状态就混乱了,因此需要重构EF Core的代码,工作量比较大。

作为一个成熟的框架,考虑这些逻辑问题以避免潜在的风险是有必要的,是可以理解的。但是作为实际的开发者,我们是有办法规避这些问题的。比如一般的Web应用中,删除操作都是在一个单独的Http请求进行中的,因此不涉及到微软担心的问题。即使在有的场景下,涉及到在通过同一个DbContext在数据删除之前就把数据查询出来的场景,那么也完全可以通过在删除之后再查一次的方式来规避这个问题。

根据github上那个issue的回复,微软有考虑在EF Core 6.0中加入高效地批量删除和更新数据的方式,但是仅仅是“考虑”,并不确定。我们作为普通开发者可等不及了,因此要自己去解决。

三、已有解决方法

有如下三种已有的解决方法:

1.     执行原生SQL语句。在EF Core中提供了ctx.Database.ExecuteSqlRaw()等方法可以用来执行原生SQL语句,因此我们可以直接编写Delete、Update语句来删除或者更新数据。这种方式比较直接,缺点就是这样代码中直接操作数据表的方式不太符合模型驱动、分层隔离等思想,程序员直接面对数据库表,无法利用EF Core强类型的特性,如果模型发生改变

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值