【问题标题】:Simple Console Application SQL Update Query - Timing Out简单控制台应用程序 SQL 更新查询 - 超时
【发布时间】:2013-04-09 01:46:03
【问题描述】:

我有以下 VB.Net 控制台应用程序子例程,它从表中读取电子邮件并尝试发送它们,如果发送成功,它将更新与发送时间相同的数据库。

这段代码运行良好,但是我现在收到以下错误:

超时。在操作完成之前超时时间已过或服务器没有响应。

我尝试在管理工作室中单独运行 SQL 脚本,它运行良好。

我也试过验证服务器空间和数据库大小,都很好。

谁能帮忙解决?

Connection(True)
    Using comSQL As New SqlCommand("SELECT * FROM Seq_Emails_ToSend", conSQL)
        Using dr As SqlDataReader = comSQL.ExecuteReader
            While dr.Read

                Dim madTO As MailAddressCollection = ConvertStringtoMAD(dr("Email_TO").ToString)
                Dim madCC As MailAddressCollection = ConvertStringtoMAD(dr("Email_CC").ToString)
                Dim madBCC As MailAddressCollection = ConvertStringtoMAD(dr("Email_BCC").ToString)
                Dim isHTML As Boolean = CBool(dr("Email_HTML").ToString)
                Dim Priority As MailPriority = CInt(dr("Email_Priority").ToString)
                Dim Subject As String = CStr(dr("Email_Subject").ToString)
                Dim Body As String = CStr(dr("Email_Body").ToString)
                Dim ID As Integer = CInt(dr("Email_ID").ToString)
                Dim Status As String

                If EmailFile(madTO, madCC, madBCC, "", isHTML, Priority, Subject, Body) Then
                    Status = "Sent"
                Else
                    Status = "Failed"
                End If

                Using comSQL2 As New SqlCommand("UPDATE Seq_Emails SET [Status] = @Status, [Date_Sent] = @Date WHERE Email_ID = @ID", conSQL)
                    comSQL2.Parameters.Add("@ID", SqlDbType.Int).Value = ID
                    comSQL2.Parameters.Add("@Status", SqlDbType.NVarChar).Value = Status
                    comSQL2.Parameters.Add("@Date", SqlDbType.DateTime).Value = DateTime.Now

                    comSQL2.ExecuteNonQuery()
                End Using

            End While
        End Using
    End Using
    Connection(False)

【问题讨论】:

  • 您是否启用了 MARS(多个活动结果集)?
  • 嗨对不起,我不知道什么是 MARS 或如何启用它?但是我知道我没有禁用它,并且上面的代码昨天还在工作,并且在过去的几个月里一直在工作。
  • 查看你的连接字符串并检查是否有子字符串MultipleActiveResultSets=True;
  • 是的 - 这是我在设置中的连接字符串:Data Source=###.###.###.###,4444;Initial Catalog=McD;User ID=Username ;Password=Password;MultipleActiveResultSets=True;连接超时=300;
  • 所以我的猜测是错误的

标签: sql-server vb.net


【解决方案1】:

我认为你在屏蔽自己。

使用一个 SqlDataReader 读取所有数据,并将其放入一个简单的 DTO 对象和 DTO 对象的集合中。 完全处置/关闭此 SqlDataReader。

然后尝试发送电子邮件,然后发出一个 UPDATE 命令。

换一种说法,尝试从 comSQL 内部 UNNEST comSQL2。

这是一个简单的 IDataReader 到 DTO 示例。

Why is DataTable faster than DataReader

【讨论】:

  • 您应该始终尽可能快地使用 IDataReader。您正在“闲逛”在 IDataReader 中发送的电子邮件,恕我直言,这不是一个好习惯。获取 IDataReader,快速使用,将数据放入 dto/dtoCollection 中,然后对 dto/dtoCollection 进行操作。
  • 谢谢 - 我确实认为这可能是问题所在,我猜数据大小可能与它突然阻塞的原因有关。我会试一试。谢谢,史蒂夫。
  • 您的 Connection(true) 可能也有一些巫术。这看起来像是有人试图变得“聪明”。看看这个帖子:stackoverflow.com/questions/328005/…
【解决方案2】:

看来我不得不取消嵌套上面提到的 2 个 sqldatareaders。

在下面的代码中,根据电子邮件处理的结果,主键被添加到列表中:

                If EmailFile(madTO, madCC, madBCC, "", isHTML, Priority, Subject, Body) Then
                    intSent.Add(CInt(dr("Email_ID").ToString))
                Else
                    intFailed.Add(CInt(dr("Email_ID").ToString))
                End If

然后,一旦发送过程完成,我就会在 2 个单独的列表或主键上运行更新查询以进行更新。

    Using comSQL2 As New SqlCommand("UPDATE Seq_Emails SET [Status] = @Status, [Date_Sent] = @Date WHERE Email_ID = @ID", conSQL)
        For Each Email_ID As Integer In intSent
            comSQL2.Parameters.Clear()
            comSQL2.Parameters.Add("@ID", SqlDbType.Int).Value = Email_ID
            comSQL2.Parameters.Add("@Status", SqlDbType.NVarChar).Value = "Sent"
            comSQL2.Parameters.Add("@Date", SqlDbType.DateTime).Value = DateTime.Now
            comSQL2.ExecuteNonQuery()
        Next
        For Each Email_ID As Integer In intFailed
            comSQL2.Parameters.Clear()
            comSQL2.Parameters.Add("@ID", SqlDbType.Int).Value = Email_ID
            comSQL2.Parameters.Add("@Status", SqlDbType.NVarChar).Value = "Failed"
            comSQL2.Parameters.Add("@Date", SqlDbType.DateTime).Value = DateTime.Now
            comSQL2.ExecuteNonQuery()
        Next
    End Using

我确信有很多更简单的方法可以做到这一点 - 但是在这种情况下它对我有用。

【讨论】:

  • 好的。您仍然与 DataReader 中的 Email_Send 一起“闲逛”。所以请记住,如果您的 smtp 服务器在任何时候变慢,整个例程可能会阻塞其他数据库请求。我仍然建议尽快重构为使用 Idatareader(推入 DTO),关闭阅读器。然后开始发送电子邮件。然后在所有电子邮件尝试之后,返回并更新行。到目前为止,DTO 重构需要一个小时,而且当 smtp 服务器变慢时,您不会阻塞其他数据库内容。
  • 嗨 - 是的,我明白你的意思了,我有这个应用程序的其他部分,它们首先将 sql 结果转储到数据表中,但这似乎目前正在工作。我将来可能会改变。为您的帮助干杯。
猜你喜欢
  • 1970-01-01
  • 2017-03-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-07-09
  • 1970-01-01
  • 1970-01-01
  • 2011-05-08
相关资源
最近更新 更多