Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a way to detect open readers on a SqlConnection?

Tags:

c#

sql-server

I am getting the error "New transaction is not allowed because there are other threads running" in an application I am working on. It has arisen during refactoring and specifically during creation of a test suite.

I realise from looking around that it means that I probably have a data reader still open when I am creating the transaction, however it's a complex app and it's not obvious to me where the problem is. Therefore I'd like to be able to work out what readers are connected to the SqlConnection in question.

Ideally I want to be able to add a watch in Visual Studio and then step through in debug mode to see when the number of connected readers change.

Is there any way to do this? I am working in C#.

Thanks in advance.

Martin

like image 252
marsbard Avatar asked Oct 28 '10 13:10

marsbard


People also ask

How do you solve error there is already an open DataReader associated with this Command which must be closed first?

There is already an open DataReader associated with this Command which must be closed first. Have you got solution for this error? Hi, Try disconnecting and reconnecting to database before executing the query.

Does SqlDataReader close connection?

The SqlConnection is closed automatically at the end of the using code block.

How do I get data from ExecuteReader?

To retrieve data using a DataReader, create an instance of the Command object, and then create a DataReader by calling Command. ExecuteReader to retrieve rows from a data source.

Is already an open DataReader associated with this connection which must be closed first?

Why do I get the error message 'There is already an open DataReader associated with this Connection which must be closed first. ' This is caused if you are attempting to use the same DataReader more than once in your code without closing the previous Datareader.


2 Answers

Phew! Well I know a lot more about Reflection now!

For anyone else looking for the answer to this, here's a method that returns the number of data readers on a SqlConnection.

public static int CountConnectedReaders(SqlConnection conn)
{
    int readers = 0;
    Type t = conn.GetType();
    MemberInfo[] minf = t.GetMembers(BindingFlags.NonPublic | BindingFlags.Instance);
    for (int i = 0; i < minf.Length; i++)
    {
    if (minf[i].Name == "get_InnerConnection")
    {                    
        MethodInfo methinf = (MethodInfo)minf[i];

        object result = methinf.Invoke(conn, new object[0]);

        PropertyInfo[] pinfs = result.GetType().GetProperties(BindingFlags.NonPublic | BindingFlags.Instance);
        foreach (PropertyInfo pinf in pinfs)
        {
        if (pinf.PropertyType.Name == "DbReferenceCollection")
        {
            object dbrc = pinf.GetValue(result, new object[0]);
            if (dbrc == null) readers = 0;
            else
            {
            MemberInfo[] dbrcInfs = dbrc.GetType().GetMembers(BindingFlags.NonPublic | BindingFlags.Instance);
            foreach (MemberInfo dbrcInf in dbrcInfs)
            {
                if (dbrcInf.Name == "_dataReaderCount")
                {
                FieldInfo finf = (FieldInfo)dbrcInf;
                readers = (Int32) finf.GetValue(dbrc);
                }
            }
            }
        }
        }
    }
    }

    return readers;
}

Interestingly, using this in my problem code suggests there are no data readers open on the connection when I get the "New transaction is not allowed because there are other threads running" error so back to the drawing board (or at least another SO question) with that.

like image 183
marsbard Avatar answered Oct 03 '22 06:10

marsbard


You might find this thread of interest.

Edit: Looks like they got at DbConnectionInternal with Reflector, and a free version is available. As for reflection, it's not too complicated really. There's a decent overview on MSDN.

Edit2: Just realized that you already figured it out. Great. :) I'll leave the edit in case somebody else wants more info.

like image 27
dandan78 Avatar answered Oct 03 '22 05:10

dandan78