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是针对整个表中数据做并发处理