VB6,ADO,异步命令和关闭连接

时间:2014-03-26 11:21:23

标签: sql-server asynchronous vb6 ado

真的很快,我是否需要关闭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,这样可以正常工作。

所以,我的问题是没有关闭连接有什么影响。连接会在后台暂停吗?请记住,此功能称为A LOT,到目前为止,测试未显示任何问题。

如果我需要在存储过程完成时关闭连接,我该怎么做?拥有C#背景,我不熟悉VB6,并且发现在运行时创建具有事件的对象是一个尴尬的过程。

P.S。 Sql Server 2008

由于

3 个答案:

答案 0 :(得分: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

答案 1 :(得分: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

答案 2 :(得分:0)

我在这里是因为我考虑在类似的实时应用程序中使用asynchExecute。在打开时将连接设置为空的问题是它可能无法正确释放,并且每创建一个新的10M,这可能会导致内存泄漏。 Mucker你应该在测试它时监视内存使用情况,看它是否发生。