2014-03-26 78 views
1

真的很快,我需要關閉一個ADO命令嗎?我已經在幾個地方看過,只是簡單地把它設置爲沒有做關閉它的同樣的事情,但我還沒有找到明確的答案。VB6,ADO,異步命令並關閉連接

我有一個VB6例程,它在運行時創建一個連接和命令對象,它們異步執行一個不返回任何結果的存儲過程。

在這個例程結束時,兩個對象都被設置爲空。下面的代碼完全顯示了執行的操作

' Open connection 
con.Open 
' 
' Create command to execute stored proc 
Set cmd = New ADODB.Command 
cmd.ActiveConnection = con 
cmd.CommandType = adCmdStoredProc 
cmd.CommandText = cSQLDelete 
cmd.Parameters.Append cmd.CreateParameter _ 
     ("@ExpiryDate=", adDate, adParamInput, 20, ExpiryDate) 
' 
' Run procedure, no results 
cmd.Execute , , adExecuteNoRecords + adAsyncExecute 
' 
' Tidy up 

Set cmd = Nothing 
Set con = Nothing 

注意不存在con.Close。如果在con = nothing之前插入它,則存儲過程不會運行 - 我假設由於它是異步的,它在連接關閉之前沒有時間執行。

沒有con.Close,這工作正常。

所以,我的問題是什麼暗示有沒有關閉連接。連接是否會在後臺簡單超時?請記住,這個功能被稱爲一個LOT,到目前爲止測試沒有顯示任何問題。

如果我需要在存儲過程完成時關閉連接,我該怎麼做?擁有C#背景,我不熟悉VB6,並發現在運行時使用事件創建對象是一個尷尬的過程。

p.s. SQL Server 2008中

感謝

+0

我鼓勵你檢查SQL Server框上的資源。具體來說,使用SQL Server Management Studio連接到它,打開查詢窗口並執行「sp_who」。我認爲你會發現很多徘徊的連接,最終可能會讓你的SQL Server變慢。這只是一個猜測(這就是爲什麼我沒有把它作爲答案)。由於它非常容易檢查,所以我鼓勵你嘗試一下。 –

回答

1

你必須等待命令完成或拆除連接之前失敗。執行命令時關閉連接會立即引發錯誤,將連接設置爲空將不會釋放它所持有的資源,並可能導致程序崩潰。

正確的方法是在命令完成時關閉連接,通常通過監視ExecuteComplete事件(您的連接必須屬於類或表單)。

可以使用類似的一個什麼東西:

Option Explicit 

Dim WithEvents con As ADODB.Connection 
Dim bExecuting As Boolean 

Private Sub cmdCancel_Click() 
    If Not bExecuting Then Exit Sub 

    If Not con Is Nothing Then 
     con.Cancel 
    End If 
    bExecuting = False 
End Sub 

Private Sub cmdExecute_Click() 
    If bExecuting Then Exit Sub 

    If con Is Nothing Then 
     Set con = New ADODB.Connection 
     con.Open "Provider=..." 
    End If 
    bExecuting = True 
    con.Execute "WAITFOR DELAY '000:00:10'", , adExecuteNoRecords + adAsyncExecute 
End Sub 

Private Sub cmdExit_Click() 
    If bExecuting Then Exit Sub 
    Unload Me 
End Sub 

Private Sub con_ExecuteComplete(ByVal RecordsAffected As Long, ByVal pError As ADODB.Error, adStatus As ADODB.EventStatusEnum, ByVal pCommand As ADODB.Command, ByVal pRecordset As ADODB.Recordset, ByVal pConnection As ADODB.Connection) 
    If Not pError Is Nothing Then Debug.Print pError.Description 
    bExecuting = False 
End Sub 

Private Sub Form_Load() 
    bExecuting = False 
End Sub 

Private Sub Form_QueryUnload(Cancel As Integer, UnloadMode As Integer) 
    If bExecuting Then Cancel = 1 
End Sub 

Private Sub Form_Unload() 
    If Not con Is Nothing Then 
     If con.State = adStateOpen Then con.Close 
     set con = Nothing 
    End If 
End Sub 
+0

謝謝你,但你在哪裏關閉連接? –

+0

看起來Form_Unload在某處丟失了,我將編輯代碼。另一個好點將直接在con_ExecuteComplete中。 – grudolf

+0

謝謝,但我有點擔心如何將它應用於我的情況(順便說一下,應用程序不是我的!) - 我會解釋。該功能是從一個定時器事件中調用的,該事件每10ms觸發一次 - 相關應用程序是一個「服務器」,在此事件中,如果沒有客戶端請求服務,它將執行管家職責。其中之一是清除舊記錄的審計數據庫。如果服務器空閒,那麼這個任務(即存儲的proc有問題)可能會被稱爲每分鐘1000次(再次,我沒有寫這個。繼續在下一個評論中。) –

0

我來這裏是因爲我在一個類似的實時應用程序中使用asynchExecute考慮。在連接打開時將連接設置爲空的問題是它可能無法正確釋放,並且每創建一個新連接10M,這可能導致內存泄漏。 Mucker你應該在你測試這個時候監視內存使用情況,看看它是否發生。

+1

您可以做的是在連接繁忙時使用字符串數組堆疊數據庫命令,並使用ExecuteComplete事件來卸載並執行它們。 – Banjaxed

+0

感謝您在這裏花時間提供詳細的答案。我已經讓應用程序運行了3天,沒有錯誤,觀察到不利的內存使用情況。因此,這表明執行SP的方式不會返回任何記錄,也不需要等待命令執行(因爲這是一個「即忘即忘」命令),這是一條可行的路線。順便說一句,服務器已經使用類似於你的方法(集合,而不是數組),但服務客戶端請求之前管家...繼續... –

+0

...管家任務必須派遣一個實例,即使SP可能需要數秒或數分鐘才能執行。由於不得不等待命令執行,雖然是異步的,但在繼續前似乎不是最好的方法。客戶端請求只能在服務器無法快速處理的情況下緩存 - 而不是因爲它正在等待內務處理任務完成。如果高壓警報關閉,並且由於內務管理任務運行需要服務器30秒作出反應,則會問到問題。 –

1

這段代碼所做的是在連接不忙的情況下執行命令(State = Open)。否則,將其放在堆棧上並在當前命令完成時執行它。我對VB數組的知識有限,所以感到抱歉有點難看 - 可能有更好的方法來做FIFO隊列?

Dim WithEvents mobjAdoConn As ADODB.Connection 
Dim CommandArray() As String 

Private Sub Command1_Click() 
Dim cmdNo As Integer 
    If mobjAdoConn.State <> adStateOpen Then 
     cmdNo = UBound(CommandArray) 
     ReDim Preserve CommandArray(cmdNo + 1) 
     CommandArray(cmdNo) = "WAITFOR DELAY '000:00:10'" 
     Label2.Caption = cmdNo 
    Else 
     mobjAdoConn.Execute "WAITFOR DELAY '000:00:10'", , adExecuteNoRecords + adAsyncExecute 
    End If 
End Sub 

Private Sub Form_Load() 
On Error GoTo Err 
    Set mobjAdoConn = New ADODB.Connection 

    mobjAdoConn.ConnectionTimeout = 30 
    mobjAdoConn.ConnectionString = "Provider..." 

    mobjAdoConn.Open 

    ReDim CommandArray(1) 
    Exit Sub 
Err: 
    MsgBox Err.Description, vbOKOnly 

End Sub 

Private Sub mobjAdoConn_ExecuteComplete(ByVal RecordsAffected As Long, ByVal pError As ADODB.Error, adStatus As ADODB.EventStatusEnum, ByVal pCommand As ADODB.Command, ByVal pRecordset As ADODB.Recordset, ByVal pConnection As ADODB.Connection) 
Dim cmd As String 
Dim i As Integer 
Dim cmds As Integer 
    cmds = UBound(CommandArray) 
    If cmds > 1 Then 
     cmd = CommandArray(1) 
     If cmds = 2 Then 
      ReDim CommandArray(1) 
      Label2.Caption = 0 
     Else 
      For i = 2 To cmds - 1 
       CommandArray(i - 1) = CommandArray(i) 
      Next i 
      ReDim Preserve CommandArray(cmds - 1) 
      Label2.Caption = cmds - 2 
     End If 
     mobjAdoConn.Execute cmd, , adExecuteNoRecords + adAsyncExecute 
    End If 
End Sub 
+0

集合對於FIFO/LIFO隊列非常方便。語法更清晰,性能應該更好。 – grudolf

相關問題