有没有一种方法可以检测SqlConnection上的打开阅读器?

10
我在我正在工作的应用程序中遇到了错误“由于其他线程正在运行,所以不允许新事务”。这是在重构和创建测试套件期间出现的。
我从搜索中了解到,这意味着当我创建事务时可能仍然有数据读取器打开,但它是一个复杂的应用程序,我不确定问题出在哪里。因此,我想找出哪些读取器连接到了相关的SqlConnection。
理想情况下,我希望能在Visual Studio中添加一个监视器并在调试模式下逐步跟踪,以查看连接读取器的数量何时发生变化。
有没有办法做到这一点?我正在使用C#。
提前感谢。
马丁
2个回答

8

哎呀!现在我对反射有更多的了解了!

对于其他需要答案的人,这里有一个方法可以返回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;
}

有趣的是,使用这个代码来解决我的问题时,似乎连接上没有打开数据读取器,当我得到“因为有其他线程正在运行,所以不允许新事务”错误时,只能回到原点(或者至少要在 Stack Overflow 上再提一个问题)。


哇,有人将我花费数小时才得出的答案投票为“无用”。我很想知道为什么。 - marsbard
到处都是傻瓜。不错的发现-我知道没有办法从文档界面获取它,但显然连接需要在某个地方引用。好吧,至少有一个打开读者的数量计数。 - TomTom
所有这些年过去了,对我来说现在显而易见的是,我上面提到的其他数据读取器是在另一个连接上的。 - marsbard

1

你可能会对这个线程感兴趣。

编辑:看起来他们用Reflector接触了DbConnectionInternal,并且有一个免费版本可用。至于反射,它其实并不太复杂。在MSDN上有一个不错的概述。

编辑2:刚意识到你已经弄明白了。太好了。:) 我会保留编辑,以防其他人需要更多信息。


那是一个有趣且相关的主题。但是当我尝试使用反射时,我有点力不从心 :) 此外,在调试模式下通过智能感知助手单击时,我找不到DBConnectionInternal。 - marsbard

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接