0

我被要求做一个系统,该系统每秒轮询数据库中的一个表,如果它对符合条件的行进行计数,则开始操作来处理它。

我已经这样做了,但时不时地我得到一个超时异常。我有一个 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 函数尝试了一些不同的方法。当我的应用程序启动并转储“使用”子句时,我现在打开一个连接。所以我的函数现在看起来像这样:

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

如果有人对此有任何想法,我真的很高兴......我不得不承认我现在真的很困惑。

4

2 回答 2

0

可能您的代码完成时间比连接的默认超时值要长。尝试在创建 Sql 连接时指定超时。确保它比您的代码需要完成的时间长。

于 2013-08-29T11:13:20.933 回答
0

这种方法似乎不太好。。与其进行池化,不如在新数据到来时做出反应?您可以使用触发器或SqlDependency 吗?

http://dotnet.dzone.com/articles/c-sqldependency-monitoring

于 2013-08-29T11:39:56.557 回答