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ましたが、ある時点でイベントが次のスタックで呼び出されることがわかりました (状態が から に変更されOpenていますClosed)。

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

私は何とかそれを回避する必要があります。明らかにランダムなネットワーク エラーが発生します。ネットワークの問題でスローされた sを処理できるコードに再試行ロジックがSqlExceptionありますが、ここでは閉じたリーダーとInvalidOperationException.

私の最初のアイデアは、ExecuteReader()ネイティブを呼び出す独自のコードを作成ExecuteReader()し、閉じられたリーダーが返されたかどうかを確認し、それが発生した場合は新しいものをスローし、ClosedReaderReturnedExceptionそのような例外にも反応してクエリを再実行するように再試行コードを変更することです。

私の解決策は良いですか?より良い解決策はありますか?

4

1 に答える 1

-1

(特定の SqlException ではなく) 例外に基づく再試行ロジックを使用することに問題はありますか? プログラミング エラーが原因で発生する例外は最終的にテスト フェーズ中に発見され、深刻な (SO などの) 例外はいずれにしても catch ブロックによってキャッチされないため、再試行ロジックの一般的な例外ブロックは許容される考えです。

そうでない場合は、おそらくラッピングのソリューションExecuteReaderが良い考えです。これは文書化された動作であることを考慮するとIOException、ExecuteReader メソッドがスローする可能性がある他の例外にも注意を払う必要がありObjectDisposedExceptionますInvalidOperationException

于 2013-01-09T07:09:38.543 に答える