您好我的应用程序中存在数据库超时问题。由于某些网络故障,查询需要超过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
答案 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()