商城首页欢迎来到中国正版软件门户

您的位置: 首页 > 文章列表 > 编程开发 > C#怎么处理EFCore并发更新_C# RowVersion时间戳冲突解决【进阶】

C#怎么处理EFCore并发更新_C# RowVersion时间戳冲突解决【进阶】

  发布于2026-07-08 阅读(0)

扫一扫,手机访问

先直接说一个核心观点:DbUpdateConcurrencyException 这个异常,与其说它是“报错”,不如把它理解为 EF Core 跟你打了个招呼,提醒你“有人动过你的数据了,你自己决定接下来怎么办”。如果你不捕获它、不配置并发令牌,那所谓的“乐观锁”策略其实根本没有生效。

C#怎么处理EFCore并发更新_C# RowVersion时间戳冲突解决【进阶】

可以把这个异常看作一次“介于成功与失败之间的汇报”。它只会在两个条件同时满足时才会被抛出:数据库中那一行的 RowVersion 值,与你加载时获取的值对不上号;并且,这个字段在 EF Core 里被正确标记成了并发令牌。很多开发者遇到这个异常就慌了神,但往往问题出在以下几个细节上:

  • 实体类上虽然打了 [Timestamp] 属性,但字段类型写错了——必须是 byte[],写成 stringint 都没用。
  • 用 Fluent API 配置时,只写了 .HasDefaultValueSql("..."),却漏掉了最关键的 .IsRowVersion()
  • 数据库迁移没跑通,导致表里的 RowVersion 字段是 NULL,SQL Server 根本不会自动生成值。
  • 手动给 RowVersion 赋了值(比如 entity.RowVersion = new byte[8]),等于自己破坏了数据库的自动维护机制。

怎么从异常里拿到真正有用的值

ex.Entries 是唯一的入口,每个 EntityEntry 会暴露三套状态,这三套数据加起来,就是你做决策的全部依据:

  • OriginalValues:你调用 FindAsyncFirstOrDefault 时从数据库读出来的旧数据,包含了旧的 RowVersion
  • CurrentValues:你修改完、准备提交的新值,这里不含新的 RowVersion —— 那是 EF Core 自动生成的活儿。
  • DatabaseValues:此刻数据库里真实的最新状态。注意,这个值需要异步获取:await entry.GetDatabaseValuesAsync()

这里必须提醒一个很容易忽略的点:DatabaseValues 可能返回 null —— 说明这条记录已经被删了。所以别急着调 .ToObject(),先判空。另外,千万别图省事在同步方法里用 .GetDatabaseValues(),那个重载已经被标记为过时,而且会卡死。

重试合并时最容易踩的三个坑

经典的处理策略是“拉最新数据 → 合并修改 → 重试提交”,但在实际代码中,经常看到开发者掉进这些坑里:

  • 没重设 OriginalValues:只调了 SetValues(databaseValues) 还远远不够,必须显式调用 entry.OriginalValues.SetValues(databaseValues),否则下一次提交时,EF Core 拿的还是一个过期的 RowVersion 去比对,结果可想而知。
  • 盲目覆盖所有字段:如果用户只改了 Name,但 DatabaseValues 里的 Price 在过程中被别人动过,你用 SetValues 一股脑全设回去,等于把别人的修改给抹平了。正确的做法是只合并用户本次操作的字段。
  • 忽略了主从表的联动:比如一个 Product 关联多个 OrderItem。主表冲突后,子表的 OriginalValues 没跟着同步刷新,二次提交仍然失败。这才是真正的“连环坑”。

RowVersion 字段在 SQL Server 之外的问题

需要明确一个事实:[Timestamp] 是 SQL Server 特有的语义。换到 PostgreSQL,你得用 bytea 类型搭配 .IsRowVersion();而到了 SQLite,它根本不支持自动 rowversion,只能退而求其次,改用 [ConcurrencyCheck] 手动维护一个 int 版本号。如果你的项目要跨多数据库,那最好在 OnModelCreating 里统一用 Fluent API 来配置,别依赖特性标注——否则 [Timestamp] 在 PostgreSQL 的迁移过程中会静默失效,而你还浑然不觉。

本文转载于:https://www.php.cn/faq/2420315.html 如有侵犯,请联系zhengruancom@outlook.com删除。
免责声明:正软商城发布此文仅为传递信息,不代表正软商城认同其观点或证实其描述。

热门关注