EF Core 乐观锁重试需捕获 DbUpdateConcurrencyException 后刷新 OriginalValues 并重试,前提是正确配置并发令牌(如 1769962489 或 Fluent API 的 IsRowVersion),否则不触发校验。
EF Core 实现乐观锁重试,核心是捕获 DbUpdateConcurrencyException 后主动刷新原始值并再次提交。它不是开箱即用的“自动重试”,而是需要你显式编写重试逻辑——但结构清晰、可控性强。
没有正确配置并发令牌,EF Core 就不会触发版本校验,自然也不会抛出并发异常。必须确保至少一个属性被标记为并发令牌:
1769962489 + byte[] 类型(如 RowVersion),SQL Server 自动维护,高效可靠[ConcurrencyCheck] 标记任
LastUpdated 或 Version),但需业务层保证更新时同步赋值modelBuilder.Entity().Property(x => x.RowVersion).IsRowVersion();
这是最常用、最可控的方式。关键在于调用 entry.OriginalValues.SetValues(databaseValues),让 EF Core 下次比较时用数据库最新值作为“原始值”:
catch (DbUpdateConcurrencyException ex) 中遍历 ex.Entries
entry.GetDatabaseValues() 获取当前库值entry.OriginalValues.SetValues(...) 覆盖原始快照context.SaveChanges() 尝试第二次提交避免重复写 try-catch,可抽成通用方法。例如:
AsNoTracking().FirstOrDefault() 获取最新状态)Reload()
如果你项目已引入 Polly,可以简洁地表达重试意图:
Policy.Handle().WaitAndRetry(3, i => TimeSpan.FromMilliseconds(Math.Pow(2, i) * 100)) context.SaveChanges() 包进策略执行块中,失败自动重试onRetry 回调,在每次重试前刷新实体原始值,保持逻辑完整基本上就这些。重试本身不复杂,但容易忽略原始值刷新这一步——没它,重试只是反复拿旧快照去比,永远失败。