You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 14:04:56