我被要求做一个系统,该系统每秒轮询一次数据库中的一个表,如果它反对符合条件的行开始处理该行的动作。
我已经做到了这一点,但我时不时地得到一个例外。我有一个WPF应用程序,我有一个在后台运行的线程。该线程有一个循环,并在循环结束时休眠一秒钟。与“数据库”的连接在“using”子句中打开。
以下是我的主题:
Private Sub PollDatabase()
While m_StopThread = False
Try
Dim listOfRows As List(Of DataObject) = db.GetDataObjects()
... Do something with the rows ...
Catch ex As Exception
m_log.WriteLine(ex.ToString())
End Try
Thread.Sleep(1000)
End While
End Sub
我的SQL函数如下所示:
Public Function GetDataObjects() As List(Of DataObject)
Dim result As New List(Of DataObject)
Dim sb As New StringBuilder("... the sql query ...")
Using cnn = New SqlConnection(_connectionString)
cnn.Open()
Using cmd = New SqlCommand(sb.ToString(), cnn)
cmd.CommandTimeout = 0
Using DataReader As SqlDataReader = cmd.ExecuteReader()
Do While DataReader.Read()
... read the columns from table
to the dataobject ...
result.Add(DataObject)
Loop
End Using
End Using
End Using
Return result
End Function
现在似乎随机的我的日志有一个超时异常:
System.Data.SqlClient.SqlException (0x80131904): Timeout expired. The timeout period elapsed prior to completion of the operation or the server is not responding.
...
at System.Data.SqlClient.SqlConnection.Open()
我的问题是:这是否可以节省这样做?或者我在这里做了一些根本错误的事情?当然,如果有人有建议解决这个问题。
编辑:
我尝试了一些与SQL函数不同的方法。我现在在应用程序启动时打开一个连接并转储“using”子句。所以我的函数现在看起来像这样:
Public Function GetDataObjects() As List(Of DataObject)
Dim result As New List(Of DataObject)
Dim sb As New StringBuilder("... the sql query ...")
_sqlCmd.CommandText = sb.ToString()
Using DataReader As SqlDataReader = _sqlCmd.ExecuteReader()
Do While DataReader.Read()
... fill the list with objects ...
Loop
End Using
Return result
End Function
我的日志是干净的表单错误。那么在一秒钟内打开与服务器的连接是否有问题,就像我使用它一样?
编辑:
我现在已经做了很多测试来确定问题。我发现只是多次连接到服务器不会导致任何问题。连接后也没有添加select语句。但是当我实际实现一个函数时,完整的阅读器部分并返回我的结果,我会遇到超时问题。这是两个例子。
这不会导致问题:
Private Sub Window_Loaded(sender As System.Object, e As System.Windows.RoutedEventArgs)
Me.DataContext = Me
m_Thread = New Thread(AddressOf ConnectionTestFunction)
m_Thread.IsBackground = True
m_Thread.Start()
End Sub
Private Sub ConnectionTestFunction()
While m_stopThread = False
Try
m_log.WriteLine("GetData (" & m_ThreadCounter & ")")
Using cnn As SqlConnection = New SqlConnection("Data Source=server;Initial Catalog=db;Integrated Security=True;MultipleActiveResultSets=True")
cnn.Open()
Using cmd As SqlCommand = New SqlCommand("SELECT * FROM Data", cnn)
Using DataReader As SqlDataReader = cmd.ExecuteReader()
Do While DataReader.Read()
Loop
End Using
End Using
End Using
Catch ex As Exception
m_log.WriteLine(ex.ToString())
End Try
m_ThreadCounter += 1
Thread.Sleep(1000)
End While
End Sub
这会导致超时错误:
Private Sub Window_Loaded(sender As System.Object, e As System.Windows.RoutedEventArgs)
Me.DataContext = Me
m_Thread = New Thread(AddressOf ConnectionTestFunction)
m_Thread.IsBackground = True
m_Thread.Start()
End Sub
Private Sub ConnectionTestFunction()
While m_stopThread = False
Try
m_log.WriteLine("GetData (" & m_ThreadCounter & ")")
Dim datarows As List(Of Data) = Me.GetData()
Catch ex As Exception
m_log.WriteLine(ex.ToString())
End Try
m_ThreadCounter += 1
Thread.Sleep(1000)
End While
End Sub
Private Function GetData() As List(Of Data)
Dim result As New List(Of Data)
Using cnn As SqlConnection = New SqlConnection("Data Source=server;Initial Catalog=db;Integrated Security=True;MultipleActiveResultSets=True")
cnn.Open()
Using cmd As SqlCommand = New SqlCommand("SELECT * FROM Data", cnn)
Using DataReader As SqlDataReader = cmd.ExecuteReader()
Do While DataReader.Read()
Dim d As New Data()
d.DataId = DataReader("DataId")
... etc fields about 10 of them ...
result.Add(d)
Loop
End Using
End Using
End Using
Return result
End Function
如果有人对此有任何想法,我真的很高兴......我不得不承认我现在真的很困惑。
答案 0 :(得分:0)
您的代码可能需要比连接的默认超时值更长的时间才能完成。尝试在创建Sql连接时指定超时。确保它比代码完成所需的时间更长。
答案 1 :(得分:0)
这种方法看起来不是很好..为什么不在新数据到来时做出反应?您可以使用触发器或SqlDependency?