数据库超时错误解决问题

时间:2011-06-01 20:36:27

标签: .net asp.net vb.net ado.net

您好我的应用程序中存在数据库超时问题。由于某些网络故障,查询需要超过45秒才能返回大约10,000行的结果集。大部分时间它的速度快达11-12秒。我的应用程序在后台运行作为预定作业。

问题是如果在将错误写入错误日志或退出之前得到超时异常,我需要尝试三次。我知道我可以将命令超时属性设置为60秒,但我还是想在退出前尝试三次。我已经为此编写了一个方法,但我认为我的方法存在一些缺陷。

现在我特意将超时设置为5秒,因为我知道这个存储过程运行需要超过25秒。我只想获得超时过期异常并编写处理它的方法。

我的问题是,如果经过2次我将连接超时设置为50,那么我的方法就会获得正确的列表,但它会再次进入我在catch语句中调用的methodname,最后不返回任何内容。看起来它正在进入递归或其他什么,但我对我错在哪里感到困惑。

任何提示或指示都有助于澄清我的概念。

Private Shared timeoutcounter As Integer = 0
Private Shared dbConnectionString As String = ConfigurationManager.AppSettings("DBConn")

Public Shared Function GetPurgeList() As DestList

    Dim AcInfo As DestInfo = Nothing
    Dim tempList As DestList= Nothing
    Dim ConnectionString As String = dbConnectionString
    Dim cn As New SqlConnection(ConnectionString)
    Dim cmd As SqlCommand = Nothing
    Dim dr As SqlDataReader = Nothing

    Try
        cn.Open()
        cmd = New SqlCommand
        With cmd
            .Connection = cn
            .CommandType = CommandType.StoredProcedure
            .CommandText = "usp_abcd"
            .CommandTimeout = 5
            dr = .ExecuteReader
            If dr.HasRows Then
                tempList = New DestList()
                While dr.Read()
                    If dr.GetName(0).ToString() = "errnum" Then
                        ErrorLogger.WriteToErrorLog("Error from stored proc usp_abcd" + CStr(dr("errnum")), dr("errmsg"))
                    Else
                        AcInfo = New DestInfo
...
//fill object
...
                           tempList.Add(AccountInfo)
                    End If
                End While
            End If
        End With

    Catch ex As Exception
       If ex.Message.ToUpper.Contains("Timeout Expired".ToUpper) Then
            timeoutcounter = timeoutcounter + 1
            If timeoutcounter > 2 Then
                timeoutcounter = 0
                ErrorLogger.WriteToErrorLog("Exception from method GetPurgeList timeoutCounter > 3 : " + ex.Message, ex.StackTrace)
            Else
------------>  GetPurgeList() 'it gets here after getting the correct list and I am confused why does it come back here again and then finally return nothing
            End If
        Else
            ErrorLogger.WriteToErrorLog("Exception from method GetPurgeList : " + ex.Message, ex.StackTrace)

        End If

    Finally
        If dr IsNot Nothing Then
            dr.Close()
            dr = Nothing
        End If
        If cmd IsNot Nothing Then
            cmd.Dispose()
            cmd = Nothing
        End If
        If cn IsNot Nothing Then
            cn.Close()
            cn.Dispose()
            cn = Nothing
        End If
    End Try
    Return tempList
End Function

2 个答案:

答案 0 :(得分:1)

从异常调用时,您不保存GetPurgeList的返回值。我的建议是完全放弃递归。创建一个循环并将datareader部分提取到它自己的函数中,并在sproc成功时简单地调用它。

我在下面展示的不是我推荐的,而是旨在展示一般的FLOW。我不确定它是否可以在不重新打开连接的情况下工作。如果我自己这样做,我会将GetPurgeList中的所有内容放入一个循环中,该循环在X迭代后终止,或者tempList不是Nothing(实际上更容易以这种方式编写它,但我希望这会使IDEA成为可能更清晰)。

Private Shared timeoutcounter As Integer = 0
Private Shared dbConnectionString As String = ConfigurationManager.AppSettings("DBConn")

Private Shared Sub ReadFromDataReader(ByVal dr as DataReader, ByRef tempList as DestList)
        If dr IsNot Nothing AndAlso dr.HasRows Then
            tempList = New DestList()
            While dr.Read()
                Dim AcInfo As DestInfo = Nothing
                If dr.GetName(0).ToString() = "errnum" Then
                    ErrorLogger.WriteToErrorLog("Error from stored proc usp_abcd" + CStr(dr("errnum")), dr("errmsg"))
                Else
                    AcInfo = New DestInfo
...
//fill object
...
                       tempList.Add(AccountInfo)
                End If
            End While
        End If

End Sub

Public Shared Function GetPurgeList() As DestList

Dim tempList As DestList= Nothing
Dim ConnectionString As String = dbConnectionString
Dim cn As New SqlConnection(ConnectionString)
Dim cmd As SqlCommand = Nothing
Dim dr As SqlDataReader = Nothing

try
   cn.Open()
    cmd = New SqlCommand
    With cmd
        .Connection = cn
        .CommandType = CommandType.StoredProcedure
        .CommandText = "usp_abcd"
    End With
Catch ex as exception
  return Nothing ' possibly rethrow error here instead, in any case, do not continue 
End Try


Try
        cmd.CommandTimeout = 5
        dr = cmd.ExecuteReader
        ReadFromDataReader(dr, tempList)

Catch ex As Exception
   If ex.Message.ToUpper.Contains("Timeout Expired".ToUpper) Then
        try
           cmd.CommandTimeout = 15
           dr = cmd.ExecuteReader
           ReadFromDataReader(dr, tempList)
        Catch ex1 as Exception
           If ex.Message.ToUpper.Contains("Timeout Expired".ToUpper) Then
              Try
                cmd.CommandTimeout =25
                dr = cmd.ExecuteReader
                ReadFromDataReader(dr, tempList)

              Catch ex As Exception
                ErrorLogger.WriteToErrorLog("Exception from method GetPurgeList : " + ex.Message, ex.StackTrace)

          End Try
          Else
            ErrorLogger.WriteToErrorLog("Exception from method GetPurgeList : " + ex.Message, ex.StackTrace)


          End If
        End Try
    End If

Finally
    If dr IsNot Nothing Then
        dr.Close()
        dr = Nothing
    End If
    If cmd IsNot Nothing Then
        cmd.Dispose()
        cmd = Nothing
    End If
    If cn IsNot Nothing Then
        cn.Close()
        cn.Dispose()
        cn = Nothing
    End If
End Try
Return tempList
End Function

答案 1 :(得分:0)

更改...

GetPurgeList() 'it gets here after getting the correct list and I am confused why does it come back here again and then finally return nothing

向..

tempList = New DestList()

tempList = GetPurgeList()