InvalidOperationException:Timeout - 递归数据库访问

时间:2013-04-09 09:55:01

标签: asp.net sql recursion timeout

目前我的一个Web应用程序出现严重问题,每天大约有六次遇到Timeout Exception。

错误:“从池中获取连接之前已经过了超时时间。这可能是因为所有池连接都在使用中并且达到了最大池大小”。

经过大量的谷歌搜索后,我发现问题与未关闭的连接有关。所以我检查了以任何方式访问数据库的所有函数,直到我偶然发现了这个:

    Private Sub getOrgas(ByVal orgID As String)
        Dim Id = orgID
        orgColl.Add(Id)
        While (Not IsNothing(Id))
            Dim conn = Database.DbWrapper.GetConnection(1, Integration.Mandanten.DatabaseType.AddonSQL)
            Dim paras As New HashSet(Of System.Data.Common.DbParameter)
            Dim orgatmp As String
            paras.Add(New SqlClient.SqlParameter("@Id", orgID))
            Dim dr = Database.DbWrapper.GetDataReaderFromStoredProcedure("stp_Orgas_Get", paras, conn)
            While dr.Read
                If Not valueInColl(CStr(dr(0))) Then
                    orgatmp = dr(0).ToString
                    orgColl.Add(orgatmp)
                    getOrgas(orgatmp)
                End If
            End While
            dr.Close()
            conn.Close()
            Id = Nothing
        End While
    End Sub

正如您所看到的,此函数执行存储过程并通过while循环运行结果,如果特定条件-valueInColl-,它将再次调用该函数。现在以这种方式可能有20个或更多的开放连接。它与通过GetDataReaderFromStoredProcedure设置的超时值无关,实际应该就足够了。可以肯定的是,我将价值翻了一倍,并将在今晚推出。我会在第二天看到它是否有帮助。 我认为问题在于,由于递归函数,同时有太多的开放连接,但我不知道如何解决这个问题。

我找不到关于如何编辑最大连接的任何内容。我甚至不确定在哪里设置它。是IIS,DB本身还是编程参数(VB.net/ASP.NET)。 如果你们能帮助我,我会很高兴。

[编辑] 好吧,有人有想法重用连接变量,但这不起作用,因为datareader仍在运行。只要它没有关闭,我就无法以任何方式重用连接,我无法关闭datareader,因为如果我这样做,我可能会丢失数据。 dr.read的while循环尚未结束,但.. 另一方面,我删除了(几乎没用)外部,并在交换中使用了一个If子句:

Private Sub getOrgas(ByVal orgID As String, ByVal con As DbConnection)
    Dim Id = orgID
    Dim conn As DbConnection
    Dim tmpOrga As String
    orgColl.Add(Id)
    If Not IsNothing(Id) Then
        If IsNothing(con) Then
            conn = Database.DbWrapper.GetConnection(1, Integration.Mandanten.DatabaseType.AddonSQL)
        Else
            conn = con
        End If
        Dim paras As New HashSet(Of System.Data.Common.DbParameter)
        paras.Add(New SqlClient.SqlParameter("@Id", orgID))
        Dim dr = Database.DbWrapper.GetDataReaderFromStoredProcedure("stp_Orgas_Get", paras, conn)
        While dr.Read
            If Not valueInColl(CStr(dr(0))) Then
                tmpOrga = dr(0).ToString
                orgColl.Add(tmpOrga)
                getOrgas(tmpOrga, conn)
            End If
        End While
        dr.close()
        conn.Close()
        Id = Nothing
    End If
End Sub

1 个答案:

答案 0 :(得分:1)

有什么理由你不能重构事情,以便每个递归使用相同的数据库连接?

我不是VB编码器,但我会按如下方式处理它

  1. 更改getOrgas()以将连接参数默认为“无”。
  2. Dim conn行更改为if IsNothing(connParameter) conn = GetConnection() else conn := connParameter;
  3. 将您的递归行更改为getOrgas(orgatmp, conn);
  4. 测试F %%%%。
  5. 我刚注意到外部While循环。它只是让你迷惑吗?它会执行多少次? ...


    我确实想知道datareader -  试试这个 - 我看到你的datareader需要在递归之前关闭,所以关闭它。

    在伪代码中 -

    dim locallist = new list();
    while dr.read
    {
      LocalList.Add dr.thing;
    }
    dr.close;
    
    foreach(thing in locallist)
    {
       if Not ValueInColl(thing) Then
         CallYourFunctionTRecursively()
       end if;
    }
    

    你跟我在一起吗?


    如果您正在尝试将一个家庭的所有成员组合在一起,那么它取决于您使用的是哪个数据库系统,但在文档中查找“Heirarchical queries”。