ASP.Net Core中Dapper仓储的async/await异步机制疑问
Dapper异步+事务的常见坑及解决办法
嘿,我猜你遇到的意外十有八九是异步任务和事务的配合出问题了——毕竟在Dapper里用异步+事务很容易踩几个经典的坑,我帮你拆解下:
最常见的问题:事务没绑定到异步操作上
你可能在调用Dapper的ExecuteAsync时,忘记把创建好的事务对象传进去了!Dapper不会自动识别当前连接的事务,必须显式指定transaction参数,否则你的插入/更新操作根本不在事务范围内执行——这会导致部分操作成功、部分失败,或者事务回滚了但某些操作已经提交,完全不符合预期。
第二个坑:异步任务没正确等待就提交事务
如果只是把异步任务加到List<Task>里,却没调用await Task.WhenAll(tasks)就直接提交事务,那你的插入/更新任务可能还没执行完,事务就已经提交(或回滚)了。这时候要么操作失败,要么事务的一致性完全失效。
修正后的代码示例
我把你的逻辑调整成符合异步+事务规范的写法:
using (var conn = new SqlConnection(yourConnectionString)) { // 异步打开连接,避免同步阻塞线程 await conn.OpenAsync(); using (var trans = conn.BeginTransaction()) { try { var tasks = new List<Task>(); if (insertList.Count > 0) { // 关键:把transaction参数传给ExecuteAsync tasks.Add(conn.ExecuteAsync( yourInsertSql, insertList, transaction: trans )); } if (updateList.Count > 0) { tasks.Add(conn.ExecuteAsync( yourUpdateSql, updateList, transaction: trans )); } // 必须等待所有异步任务执行完成,再提交事务 await Task.WhenAll(tasks); // 所有操作都成功了,再提交事务 trans.Commit(); } catch (Exception ex) { // 任何一个任务失败,立即回滚事务 trans.Rollback(); // 这里可以加日志、异常包装等处理逻辑 throw; } } }
几个关键注意点
- 显式绑定事务:所有在事务内的Dapper异步操作,都必须传入
transaction: trans参数,否则操作会脱离事务管控。 - 等待所有任务完成:
Task.WhenAll会等待列表里的所有异步任务执行完毕,确保插入和更新都成功后再提交事务,这是保证数据一致性的核心。 - 异步打开连接:用
await conn.OpenAsync()代替同步的conn.Open(),符合ASP.NET Core异步编程的最佳实践,避免阻塞线程池线程。 - 异常回滚:只要有任何一个异步任务抛出异常,都会进入
catch块执行回滚,确保不会出现部分数据提交的情况。
内容的提问来源于stack exchange,提问作者Kane
相关产品推荐
相关产品推荐

