EFCore-并发
EFCore-并发
最好的解决并发的方案是使用非数据库解决方案来解决并发问题
悲观锁
在操作数据之前,给被操作数据加锁,如果数据已经存在锁,则一直等待
如数据库锁,行锁,表锁
EFCore没有封装悲观并发控制的使用,需要开发人员编写原生的SQL语句来使用悲观并发控制
不同数据库的语法不同,如MySQL中,使用select …… for update来实现
在.NET中实现数据库层面的锁,需要通过原生SQL的方式实现,并且锁是跟事务有关,所以需要先调用BeginTransaction方法开启事务,在操作完成后调用commit方法提交事务
乐观锁
EFCore提供了一个并发修改令牌
的概念,在进行映射时,将列通过IsConcurrencyToken方法设置为并发修改令牌
在每次更新数据库中的数据时,EFCore都会先读取并发修改令牌,并且作为update语句的where条件
这时,老数据被作为更新条件,当出现并发问题时,受影响行数将为0,则EFCore会抛出DbUpdateConcurrencyException(并发冲突)异常
RowVersion
相当于MyBatisPlus的乐观锁中的version列
在配置映射时,使用方法IsRowVersion将列配置成版本列
当数据被改变时,该列数据都会自动被框架改变
在 Entity Framework Core (EF Core) 中,如果你定义了一个 byte[]
类型的属性并标记它为 IsRowVersion()
,EF Core 会默认将该字段映射到 PostgreSQL 数据库中的 bytea
当然,RowVersion的根本作用也是为了解决并发问题,所以其原理也是乐观锁,每次修改数据之前也会取RowVersion的数据作为查询条件,当受影响行数为0时,抛出异常
并发修改令牌和RowVersion
同样是在EFCore中解决并发问题,并发修改令牌只在单列数据被影响时修改,也就是修改本身时做并发处理
而RowVersion是针对整个表中数据做并发处理