1

我有一个这样的开放SqlConnection代码:

using (var transaction = connection.BeginTransaction()) {
   using (var command = connection.CreateCommand()) {
       command.Transaction = transaction;
   command.CommandText = "MyQueryText";
       using( var reader = command.ExecuteReader() ) {
           //read data
       }
   }
}

我一直在经历一些“不可能的代码”症状并订阅了SqlConnection.StateChange事件,现在我发现在某些时候使用以下堆栈调用事件(状态正在从更改OpenClosed):

at MyHandler.onStateChange(Object sender, StateChangeEventArgs e)
at System.Data.ProviderBase.DbConnectionInternal.CloseConnection(DbConnection owningObject, DbConnectionFactory connectionFactory)
at System.Data.SqlClient.SqlConnection.Close()
at System.Data.SqlClient.SqlInternalConnectionTds.BreakConnection()
at System.Data.SqlClient.TdsParserStateObject.ReadSniError(TdsParserStateObject stateObj, UInt32 error)
at System.Data.SqlClient.TdsParserStateObject.ReadSni(DbAsyncResult asyncResult, TdsParserStateObject stateObj)
at System.Data.SqlClient.TdsParserStateObject.ReadNetworkPacket()
at System.Data.SqlClient.TdsParserStateObject.ReadByte()
at System.Data.SqlClient.SqlDataReader.SetMetaData(_SqlMetaDataSet metaData, Boolean moreInfo)
at System.Data.SqlClient.TdsParser.Run(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj)
at System.Data.SqlClient.SqlDataReader.ConsumeMetaData()
at System.Data.SqlClient.SqlDataReader.get_MetaData()
at System.Data.SqlClient.SqlCommand.FinishExecuteReader(SqlDataReader ds, RunBehavior runBehavior, String resetOptionsString)
at System.Data.SqlClient.SqlCommand.RunExecuteReaderTds(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, Boolean async)
at System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method, DbAsyncResult result)
at System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method)
at System.Data.SqlClient.SqlCommand.ExecuteReader(CommandBehavior behavior, String method)
at System.Data.SqlClient.SqlCommand.ExecuteReader()
// my code calling `ExecuteReader()`

所以运行时遇到一些随机错误(我猜是网络连接问题)并关闭连接,然后将关闭的阅读器对象返回给我的代码,并尝试使用返回的阅读器 yield InvalidOperationException

我需要以某种方式解决它。显然会发生随机网络错误。我的代码中有重试逻辑,可以处理SqlException网络问题引发的 s,但在这里我面对的是一个封闭的阅读器,然后是一个InvalidOperationException.

我的第一个想法是编写自己的ExecuteReader()调用 native 的方法ExecuteReader(),检查是否返回了已关闭的阅读器,如果发生这种情况,则抛出一个新的ClosedReaderReturnedException,我还将更改重试代码,以便它也对此类异常做出反应并重新运行查询。

我的解决方案好吗?有更好的解决方案吗?

4

1 回答 1

-1

基于任何异常(而不是特定 SqlException)的重试逻辑是否有任何问题?我假设由于编程错误导致的异常最终会在测试阶段被发现,并且严重的(例如 SO)异常无论如何都不会被 catch 块捕获,因此用于重试逻辑的通用异常块是可以接受的想法。

如果不是,那么您的包装解决方案可能是个ExecuteReader好主意。考虑到这是记录在案的行为,您还需要注意 ExecuteReader 方法可能抛出的其他异常 - 因此您可能需要预测IOExceptionObjectDisposedException远离InvalidOperationException.

于 2013-01-09T07:09:38.543 回答