2013-04-09 59 views
1

目前我的一个Web应用程序出现严重问题,每天大约有六次运行时间超时。InvalidOperationException:超时 - 递归数据库访问

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

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

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设置为600的超时值无关,这实际上应该足够了。可以肯定的是,我将价值翻了一番,并将在今晚推出。那么我会在第二天看到这是否有帮助。 我相信问题在于,由于递归函数,同时存在太多打开的连接,但我不知道如何解决这个问题。

我找不到任何有关如何编辑最大连接的内容。我甚至不确定在哪里设置它。它是IIS,数据库本身还是编程参数(VB.net/ASP.NET)。 如果你们可以帮我在这里,会很好。

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

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

有什么你不能重构的原因,使每个递归使用相同的数据库连接?

我不是一个VB编码器,但如下

  1. 变化getOrgas()采取连接参数默认为“无”我会解决它。
  2. 更改Dim conn线if IsNothing(connParameter) conn = GetConnection() else conn := connParameter;
  3. 更改您的递归线getOrgas(orgatmp, conn);
  4. 测试歼%%%%出来。

我刚刚注意到外围的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查询”你的文档。

+0

啊,这是一个伟大的想法。所以我基本上使用一个连接而不是一个接一个打开,然后关闭它们。我会检查一下。多谢,伙计。 :) – OhSnap 2013-04-09 10:20:29

+0

我认为是这样,但它取决于StoredProc在做什么 - 如果在那里有提交和回滚,它可能会开始变得非常混乱。 – 2013-04-09 10:21:50

+0

嗯..其实我不是100%确定为什么我插入另一个,但我可能需要它..现在,我看它,但它似乎几乎没用。稍后我会看看它。存储过程是一个简单的select语句。 – OhSnap 2013-04-09 10:32:49