如何从DbUpdateConcurrencyException获取自定义调用方法栈?
DbUpdateConcurrencyException栈追踪缺失自定义调用链问题
当调用DbContext.SaveChangesAsync触发DbUpdateConcurrencyException时,记录的栈追踪仅显示到自定义MyContext.SaveChangesAsync,无法看到上层自定义调用链(比如UpdateOrder等方法,直至控制器层级)。当前栈追踪如下:
at Microsoft.EntityFrameworkCore.Update.AffectedCountModificationCommandBatch.<ThrowAggregateUpdateConcurrencyExceptionAsync>d__11.MoveNext() at Microsoft.EntityFrameworkCore.Update.AffectedCountModificationCommandBatch.<ConsumeResultSetAsync>d__5.MoveNext() at Microsoft.EntityFrameworkCore.Update.AffectedCountModificationCommandBatch.<ConsumeAsync>d__3.MoveNext() at Microsoft.EntityFrameworkCore.Update.ReaderModificationCommandBatch.<ExecuteAsync>d__50.MoveNext() at Microsoft.EntityFrameworkCore.Update.ReaderModificationCommandBatch.<ExecuteAsync>d__50.MoveNext() at Microsoft.EntityFrameworkCore.SqlServer.Update.Internal.SqlServerModificationCommandBatch.<ExecuteAsync>d__17.MoveNext() at Microsoft.EntityFrameworkCore.Update.Internal.BatchExecutor.<ExecuteAsync>d__9.MoveNext() at Microsoft.EntityFrameworkCore.Update.Internal.BatchExecutor.<ExecuteAsync>d__9.MoveNext() at Microsoft.EntityFrameworkCore.Update.Internal.BatchExecutor.<ExecuteAsync>d__9.MoveNext() at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.StateManager.<SaveChangesAsync>d__106.MoveNext() at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.StateManager.<SaveChangesAsync>d__110.MoveNext() at Microsoft.EntityFrameworkCore.SqlServer.Storage.Internal.SqlServerExecutionStrategy.<ExecuteAsync>d__7`2.MoveNext() at Microsoft.EntityFrameworkCore.DbContext.<SaveChangesAsync>d__64.MoveNext() at Microsoft.EntityFrameworkCore.DbContext.<SaveChangesAsync>d__64.MoveNext() at MyProject.MyContext.<SaveChangesAsync>d__180.MoveNext() in C:\Projects\MyProject\MyContext.cs:line 315
相关代码
偶尔触发异常的SaveChangesAsync调用方法
public async Task SaveChangesAsyncCallerToReproduceTheProblem() { try { await _context.SaveChangesAsync(); } catch (DbUpdateConcurrencyException e) { _logger.LogDebug(e, "Failed to update..."); throw; } catch (Exception e) { _logger.LogDebug(e, "Failed to update..."); throw; } }
自定义DbContext的SaveChangesAsync重写实现
public override async Task SaveChangesAsync(CancellationToken cancellationToken = new CancellationToken()) { SetUpdatedAt(); await base.SaveChangesAsync(acceptAllChangesOnSuccess, cancellationToken); }
Startup中DbContext的注入配置
services.AddDbContext<MyContext>((serviceProvider, options) => { options.UseSqlServer(sqlConnectionString); });
疑问
- 是否存在操作错误?
- 能否让栈追踪显示完整的自定义调用方法链?
- 如果有解决方案,是否会引入性能损耗?
补充信息
- 将测试应用部署到Azure后,App Insights中出现两条异常记录:一条与本地栈追踪类似,另一条包含完整的自定义调用链。目前已通过该记录完成排查,不再深入本地问题。
- 该问题根源可能与异步调用栈特性有关。
- 已将触发异常的调用方法重命名为
SaveChangesAsyncCallerToReproduceTheProblem,修正了原命名的代码异味。
内容的提问来源于stack exchange,提问作者Mykola
相关产品推荐
相关产品推荐

