2013-04-16 64 views
0

我有以下VB.Net控制檯應用程序子程序,它從表中讀取電子郵件並嘗試發送它們,如果它發送成功,它將更新與發送的相同的數據庫時間。簡單控制檯應用程序SQL更新查詢 - 時間輸出

此代碼是工作的罰款,但我現在收到以下錯誤:

Timeout expired. The timeout period elapsed prior to completion of the operation or the server is not responding.

我已經試過在管理工作室單獨運行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) 
+0

您是否已啓用MARS(多活動結果集)? – Steve

+0

嗨對不起,我不知道MARS是什麼或者如何啓用它?不過,我知道我沒有禁用它,上面的代碼昨天工作,並已在過去幾個月。 – Steve

+0

看看你的連接字符串,並檢查是否有一個子字符串'MultipleActiveResultSets = True;' – Steve

回答

1

我想你是在阻止自己。

使用一個SqlDataReader讀取所有數據,並將其放入一個簡單的DTO對象並存放DTO對象。 完全處理/關閉此SqlDataReader。

然後嘗試發送電子郵件,然後發出單個UPDATE命令。

另一種說法是,從comSQL內部嘗試UNNEST comSQL2。

這是一個簡單的IDataReader到DTO的例子。

Why is DataTable faster than DataReader

+0

您應該儘可能快地使用IDataReader。你在IDataReader中發送的電子郵件「閒逛」,這是不好的做法,恕我直言。獲取IDataReader,快速使用它,將數據放入dto/dtoCollection中,然後對dto/dtoCollection執行一些操作。 – granadaCoder

+0

謝謝 - 我確實認爲這可能是問題,我猜數據大小可能與突然阻塞的原因有關。我會放棄它。謝謝,史蒂夫。 – Steve

+0

你的連接(真)也可能有一些巫術。這看起來像有人試圖「聰明」。看看這篇文章:http://stackoverflow.com/questions/328005/c-sharp-closing-sql-objects-best-practice – granadaCoder

0

看來,我不得不取消嵌套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 

我敢肯定有更簡單的方法來做到這一點 - 但它在這種情況下做了我的伎倆。

+0

好的。 DataReader內部的Email_Send仍然「掛出」。所以請記住,如果您的smtp服務器在任何時候都變慢,整個例程可能會阻止其他數據庫請求。我仍然建議儘快重構使用Idatareader(推入DTO's),關閉閱讀器。然後開始發送電子郵件。然後,在所有電子郵件嘗試後,返回並更新行。你到目前爲止,DTO重構需要一個小時,並且當smtp服務器變慢時你不會阻塞其他數據庫的東西。 – granadaCoder

+0

嗨 - 是的,我看到你的觀點,我有這個應用程序的其他部分,首先將sql結果轉儲到數據表,但是這似乎現在工作。我將來可能會改變。歡呼你的幫助。 – Steve

相關問題