ASP.NET Core & EF Core:并发异常未抛出问题求助
排查书籍预约功能并发异常未触发的问题
核心问题:测试场景未命中真正的并发条件
你的代码里有前置判断:if (book == null || !book.IsAvailable) return RedirectToAction("Index");。如果两个请求不是严格同时执行,第一个请求完成后已将IsAvailable设为false,第二个请求查询时会直接触发该判断返回,根本不会走到SaveChanges步骤,自然不会抛出DbUpdateConcurrencyException。
要测试真正的并发,需让两个请求**同时查询到IsAvailable = true**再尝试保存。可在第一个请求的查询后、保存前添加延迟模拟耗时操作:
var book = await _context.Books.FirstOrDefaultAsync(b => b.Id == id); if (book == null || !book.IsAvailable) { return RedirectToAction("Index"); } // 添加延迟,给另一个请求留出查询时间 await Task.Delay(5000); // 后续预约逻辑...
同时触发两个请求,此时两个请求都会进入保存步骤,第二个请求会触发并发异常。
代码中的冗余操作可能干扰并发检查
你调用了_context.Books.Update(book),但book是通过_context.Books.FirstOrDefaultAsync查询出来的,已被EF上下文跟踪。修改实体属性(book.IsAvailable = false)后,上下文会自动将实体标记为Modified,无需手动调用Update。
Update方法对已跟踪的实体无实质作用,但可能意外覆盖你手动设置的RowVersion原始值。建议删除这行冗余代码:
// 移除这行代码 // _context.Books.Update(book);
其他排查点
- 确认RowVersion传递正确:检查视图中隐藏域名称是否与Action参数
RowVersion一致,确保传递的是预约前的旧版本值:<input type="hidden" name="RowVersion" value="@Convert.ToBase64String(Model.RowVersion)" /> - 验证数据库字段配置:确认Book表的
RowVersion字段是SQL Server的timestamp/rowversion类型([Timestamp]特性会自动映射该类型,可手动核对数据库结构)。 - 检查EF上下文并发配置:
[Timestamp]特性已自动将该属性标记为并发令牌,此配置无需额外调整。
内容的提问来源于stack exchange,提问作者johny_walker
相关产品推荐
相关产品推荐

