C# 了解,;重现ExecuteReader InvalidOperationException(“连接的当前状态为打开”)

C# 了解,;重现ExecuteReader InvalidOperationException(“连接的当前状态为打开”),c#,sql-server,executereader,C#,Sql Server,Executereader,我收到一位用户的报告,称他们在使用我的应用程序时遇到此异常: ExecuteReader requires an open and available Connection. The connection's current state is open. | System.InvalidOperationException | at System.Data.SqlClient.SqlConnection

我收到一位用户的报告,称他们在使用我的应用程序时遇到此异常:

ExecuteReader requires an open and available Connection. The connection's current state is open.
                     |  System.InvalidOperationException
                     |     at System.Data.SqlClient.SqlConnection.GetOpenConnection(String method)
                     |     at System.Data.SqlClient.SqlConnection.ValidateConnectionForExecute(String method, SqlCommand command)
                     |     at System.Data.SqlClient.SqlCommand.ValidateCommand(String method, Boolean async)
                     |     at System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method, TaskCompletionSource`1 completion, Int32 timeout, Task& task, Boolean asyncWrite)
                     |     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()
                     |     at MyProject.Database.GetData(DataType data, SqlConnection& _conn)
然而,我似乎无法重现这个异常,事实上我甚至不知道它是什么意思:即,如果连接的当前状态是打开的,那么问题出在哪里?为什么会有例外

我尝试过单步执行代码,连接状态为打开,但它只是正确读取数据。事实上,微软文档似乎暗示,如果连接关闭,就会发生这种情况,但正如您从异常消息中看到的,它是打开的

以下是相关代码:

    private int GetData(DataType data, ref SqlConnection _conn)
    {
        string sqlStr = string.Format("select top 1 * from dbo.DataTable where [Id] = N'{0}'", data.Id);

        using (SqlCommand cmd = new SqlCommand(sqlStr, _conn))
        {
            SqlDataReader rs = null;
            try
            {
                if (_trans != null) cmd.Transaction = _trans;
                rs = cmd.ExecuteReader();

                if (rs == null)
                    return DB_ERROR;

                int attI = rs.GetOrdinal("FileData");
                int fileNameI = rs.GetOrdinal("FileName");

                while (rs.Read())
                {
                    dataFile.FileData = (byte[]) rs.GetValue(attI);
                    dataFile.FileName = DBCommon.ColStr(rs, fileNameI);
                }

                rs.Close();
                rs = null;
                return DB_OK;
            }
            catch (Exception e)
            {
                LogException(e);
                return DB_ERROR;
            }
            finally
            {
                if (rs != null)
                    rs.Close();
                rs = null;
            }
        }
    }
在调试时,我检查
_conn.State
属性,检查它是否是
打开的
,然后逐步执行
rs=cmd.ExecuteReader()行,但它处理得很好

应该注意的是,这是一个非常大的应用程序,有许多表,每个表都有自己的方法,类似于上面的一个,都引用了
\u conn
对象。重组它是不可行的


任何其他问题都有关于如何预防它的答案,但我正试图重现它,并理解它发生的确切原因

获取传入的
SqlConnection
而不是自己创建连接的方法总是可疑的。有没有可能从多个线程获得一个连接对象?ADO.NET操作上很少有线程安全的操作。此代码还有其他警告信号(如不使用
使用
读卡器、捕获
异常
、使用错误返回值和模糊的“帮助器方法使事情变得更简单”),但让我们暂时忽略这些。更令人担忧的是,参数被声明为
ref
。此方法不会替换该值,但是否有其他方法可以替换该值?这使得跟踪实际使用的连接更加危险。如果
ref
-ness没有在任何地方使用,这可能只是作者不理解引用类型如何工作的一个怪癖,或者是某个习惯于经典VB的人(其中传递值/引用的区别要明确得多)。