有没有办法在SqlConnection上检测开放阅读器?

时间:2010-10-28 13:08:45

标签: c# sql-server

我在我正在处理的应用程序中收到错误“不允许新事务,因为还有其他线程正在运行”。它是在重构期间出现的,特别是在创建测试套件期间。

我从环顾四周意识到这意味着我在创建事务时可能还有一个数据阅读器仍处于打开状态,但它是一个复杂的应用程序,对我来说问题不明显。因此,我希望能够找出读者连接到有问题的SqlConnection的内容。

理想情况下,我希望能够在Visual Studio中添加监视,然后在调试模式中单步执行以查看连接的读取器的数量何时发生变化。

有没有办法做到这一点?我在C#工作。

提前致谢。

马丁

2 个答案:

答案 0 :(得分: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;
}

有趣的是,在我的问题代码中使用它表明当我得到“不允许新事务,因为还有其他线程正在运行”错误时,连接上没有数据读取器打开,所以回到绘图板(或者至少是另一个那个问题)。

答案 1 :(得分:1)

您可能会发现此感兴趣的thread

修改:看起来他们DbConnectionInternal获得了Reflector,并且提供免费版本。至于反思,真的不是太复杂。在MSDN上有一个不错的概述。

Edit2:刚刚意识到你已经弄明白了。大。 :)我会离开编辑以防其他人想要更多信息。