ASP.NET Core 8 Web API中EF Core 8 ExecuteUpdateAsync报错求助
问题分析与解决方案
报错This SqlTransaction has completed; it is no longer usable本质是EF Core尝试使用已完成(提交/回滚)或失效的事务执行更新操作,常见触发原因包括:
- DbContext实例已被释放(比如生命周期管理错误)
- 外部事务提前完成但代码仍在使用上下文
- 查询条件中的空值(如
toUpdateMailList为null)导致查询失败,触发事务异常终止
修复后的代码示例
基础修复:处理空值+确保上下文有效性
private async Task DemoUpdateTestTable(DemoReq demoReq, IEnumerable<string>? toUpdateMailList, CancellationToken cancellationToken) { // 提前处理空值,避免Contains引发异常导致事务失效 if (toUpdateMailList == null || !toUpdateMailList.Any()) return; // 确认DbContext是Scoped注入(ASP.NET Core默认),确保在当前请求周期内有效 await _demoDbContext.TestTable .Where(recordsToUpdate => toUpdateMailList.Contains(recordsToUpdate.EmailAddress) && recordsToUpdate.Id == demoReq.Id) .ExecuteUpdateAsync(setters => setters .SetProperty(r => r.ModifyUserId, demoReq.CreateUserId) .SetProperty(r => r.ModifyDate, demoReq.ModifyDate) .SetProperty(r => r.IsApproved, r => !r.IsApproved ? null : (bool?)null), cancellationToken); }
显式事务管理(适用于需要多操作原子性的场景)
如果该方法需要和其他数据库操作共享事务,显式控制事务生命周期:
private async Task DemoUpdateTestTable(DemoReq demoReq, IEnumerable<string>? toUpdateMailList, CancellationToken cancellationToken) { if (toUpdateMailList == null || !toUpdateMailList.Any()) return; using var transaction = await _demoDbContext.Database.BeginTransactionAsync(cancellationToken); try { await _demoDbContext.TestTable .Where(recordsToUpdate => toUpdateMailList.Contains(recordsToUpdate.EmailAddress) && recordsToUpdate.Id == demoReq.Id) .ExecuteUpdateAsync(setters => setters .SetProperty(r => r.ModifyUserId, demoReq.CreateUserId) .SetProperty(r => r.ModifyDate, demoReq.ModifyDate) .SetProperty(r => r.IsApproved, r => !r.IsApproved ? null : (bool?)null), cancellationToken); // 若有其他数据库操作,在此添加 await transaction.CommitAsync(cancellationToken); } catch { await transaction.RollbackAsync(cancellationToken); throw; // 重新抛出异常让上层处理 } }
额外注意事项
- 确保
_demoDbContext是通过ASP.NET Core的依赖注入系统注入的Scoped实例(避免Singleton导致的上下文复用问题) - 检查调用该方法的上层代码是否存在提前释放DbContext或终止事务的逻辑
- 对于
IsApproved的赋值逻辑,可以简化为r => r.IsApproved ? null : (bool?)null(逻辑等价,更简洁)
内容的提问来源于stack exchange,提问作者santosh kumar patro
相关产品推荐
相关产品推荐

