省略async/await导致Dapper数据库连接异常?求原因解析
问题场景代码
Dapper封装的查询方法
public async Task<T> QuerySingleAsync<T>(string sql) { return await connection.QuerySingleAsync<T>(sql); }
调用查询方法的GetData1
public async Task<int> GetData1() { return await aboveClass.QuerySingleAsync<int>(GET_DATA_SQL); }
引发异常的GetData2写法
public Task<int> GetData2() { return aboveClass.GetData1(); }
执行var messages = await GetData2();时抛出的异常:
System.InvalidOperationException: BeginExecuteNonQuery requires an open and available Connection. The connection's current state is open.
at Microsoft.Data.SqlClient.SqlCommand.ValidateCommand(Boolean isAsync, String method)
at Microsoft.Data.SqlClient.SqlCommand.BeginExecuteNonQueryInternal(CommandBehavior behavior, AsyncCallback callback, Object stateObject, Int32 timeout, Boolean inRetry, Boolean asyncWrite)
at System.Threading.Tasks.TaskFactory1.FromAsyncImpl(Func3 beginMethod, Func2 endFunction, Action1 endAction, Object state, TaskCreationOptions creationOptions)
at Microsoft.Data.SqlClient.SqlCommand.InternalExecuteNonQueryAsync(CancellationToken cancellationToken)
--- End of stack trace from previous location ---
at Dapper.SqlMapper.ExecuteImplAsync(IDbConnection cnn, CommandDefinition command, Object param) in /_/Dapper/SqlMapper.Async.cs:line 678
修改后正常运行的GetData2写法
public async Task<int> GetData2() { return await aboveClass.GetData1(); }
问题分析与结论
省略async/await本身不会直接引发这个连接异常,这种写法本质是任务转发,属于异步代码的合理优化(避免生成不必要的状态机)。出现异常的核心原因是代码中数据库连接的生命周期管理存在问题:
- 可能是复用了同一个非线程安全的
IDbConnection实例执行多个异步操作,导致连接状态冲突 - 或者连接被提前关闭/释放,与异步操作的执行时序不匹配
加上async/await后正常运行只是巧合:async/await生成的状态机间接改变了代码执行时序,刚好避开了连接状态的冲突,但这并没有解决根本问题。
正确解决方向
- 严格管理连接生命周期:使用
using语句确保连接被正确创建、使用和释放,避免复用连接实例:
public async Task<T> QuerySingleAsync<T>(string sql) { using (var connection = new SqlConnection("你的数据库连接字符串")) { await connection.OpenAsync(); return await connection.QuerySingleAsync<T>(sql); } }
- 禁止并发复用同一个连接实例:
IDbConnection并非线程安全,多个异步操作共用同一连接必然引发状态异常。
内容的提问来源于stack exchange,提问作者Imran Qadir Baksh - Baloch

