How to address SqlConnection being closed from inside ExecuteReader?

拥有回忆 提交于 2019-12-13 03:27:39

问题


I have an open SqlConnection and code like this:

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

I've been experiencing some "impossible code" symptoms and subscribed to SqlConnection.StateChange event and now I've found that at some point the event is invoked with the following stack (state is being changed from Open to 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()`

so the runtime encounters some random error (network connectivity problem I guess) and closes the connection and then returns a closed reader object to my code and my attempts to use the returned reader yield InvalidOperationException.

I need to work it around somehow. Obviously random network errors will happen. I have retry logic in my code that can deal with SqlExceptions thrown on network issues but here I face a closed reader and then an InvalidOperationException.

My first idea is to write my own ExecuteReader() that would call native ExecuteReader(), check whether a closed reader is returned and if that happens throw a new ClosedReaderReturnedException and I'll also change the retry code so that it reacts to such exceptions too and reruns the query.

Is my solution good? Is there a better solution?


回答1:


Is there any issue with having retry logic based on any exception (and not on specific SqlException)? I am assuming that exceptions resulting due to programming errors would be eventually found out during testing phase and severe (such as SO) exceptions would anyway not be caught by catch block so generic exception block for retry logic can be acceptable idea.

If not then probably your solution of wrapping ExecuteReader would be good idea. Considering that this is documentated behavior, you also need to pay attentions to other exceptions that ExecuteReader method may throw - so you probably may need to anticipate IOException and ObjectDisposedException apart from InvalidOperationException.



来源:https://stackoverflow.com/questions/14229310/how-to-address-sqlconnection-being-closed-from-inside-executereader

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!