EF Core乐观并发锁通过版本校验实现,不阻塞操作,推荐用1766283623标记byte[]字段自动管理;也可用[ConcurrencyCheck]标记业务字段手动维护版本;冲突时抛DbUpdateConcurrencyException,可重载、合并或重试。

EF Core 乐观并发锁的核心是“不锁数据,只校验版本”,适合读多写少、冲突概率低的场景。它不阻塞其他读写操作,而是在 SaveChanges() 时通过 WHERE 条件比对版本值来判断数据是否被他人修改过。一旦发现不一致,就抛出异常,由你决定如何处理。
加一个 RowVersion 字段并标记为并发令牌
这是最推荐、最省心的方式,尤其在 SQL Server 中天然支持 rowversion 列。
- 在实体类中添加
byte[]类型字段,并用 1766283623 特性标记:
public class Product
{
public int Id { get; set; }
public string Name { get; set; }
public decimal Price { get; set; }
1766283623 // 自动映射为 rowversion(SQL Server)或 bytea(PostgreSQL)
public byte[] RowVersion { get; set; }
}登录后复制
- 或者用 Fluent API 在
OnModelCreating中配置(效果等同):
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Product>()
.Property(p => p.RowVersion)
.IsRowVersion(); // EF Core 会自动设为不可写、每次更新自增
}登录后复制
注意:该字段无需手动赋值,SQL Server 每次 INSERT/UPDATE 都会自动生成新值;EF Core 会在 UPDATE 语句的 WHERE 子句中自动带上它。
用普通字段做并发检查(灵活但需自己维护)
如果你用的是 MySQL、SQLite 或不想依赖数据库特性,可以用业务字段(如 LastModified、Version)当并发令牌。
- 用 [ConcurrencyCheck] 标记字段:
public class Order
{
public int Id { get; set; }
public string OrderNumber { get; set; }
[ConcurrencyCheck]
public int Version { get; set; } // 手动递增
}登录后复制
- 或用 Fluent API 配置:
modelBuilder.Entity<Order>()
.Property(o => o.Version)
.IsConcurrencyToken();登录后复制
关键点:你得在每次更新前主动给 Version 加 1(比如 entity.Version++),否则校验永远通过——EF Core 只负责在 SQL 的 WHERE 中加入 AND Version = 原值,不帮你管理值本身。
标签: mysql
还木有评论哦,快来抢沙发吧~