Running multiple async queries with ADODB - callbacks not always firing

后端 未结 3 556
时光取名叫无心
时光取名叫无心 2020-12-05 16:07

I have an Excel workbook that fires three queries to a database to populate three tables on hidden sheets, and then runs three \'refresh\' scripts to pull this data through

3条回答
  •  庸人自扰
    2020-12-05 16:49

    I can give you an answer that will help you some of the time, but not all the time.

    Sometimes your Recordset.Open or your Command.Execute ignores the AdAsynchFetch parameter.

    That is to say: the problem manifests immediately, when you are requesting, and it's not an issue with the application in an unresponsive state when ADODB calls back with a populated recordset.

    Fortunately, this is something you can trap in the code; and there are three things that occur when AdFetchAsynch is ignored:

    1. The Execute or Open method runs synchronously and populates a recordset.
    2. The ExecuteComplete event is never raised.

    You can see where I'm going with this...

    If your recordset-requesting code detects an open recordset before it exits, pass the open recordset straight into your existing _FetchComplete event procedure:

    
    Set m_rst = New ADODB.Recordset  ' declared at module level With Events
    With m_rst
    Set .ActiveConnection = ThisWorkbook.MyDBConnection
    .CursorType = adOpenForwardOnly
    Err.Clear .Open SQL, , , , adCmdText + adAsyncFetch
    End With
    If m_rst.State = adStateOpen Then
    ' This block will only run if the adAsyncFetch flag is ignored If m_rst.EOF And m_rst.BOF Then MsgPopup "No matching data for " & DATASET_NAME, vbExclamation + vbOKOnly, "Empty data set", 90 ElseIf m_rst.EOF Then m_rst.MoveFirst m_rst_FetchComplete Nothing, GetStatus(m_rst), m_rst Else m_rst_FetchComplete Nothing, GetStatus(m_rst), m_rst End If
    Set m_rst = Nothing
    ElseIf m_rst.ActiveConnection.Errors.Count > 0 Then
    m_rst_FetchComplete m_rst.ActiveConnection.Errors(0), adStatusErrorsOccurred, m_rst Set m_rst = Nothing
    ElseIf Err.Number <> 0 Then
    MsgPopup "Microsoft Excel returned error &H" & Hex(Err.Number) & ": " & Err.Description, vbCritical + vbOKOnly, "Error requesting " & DATASET_NAME, 60 Set m_rst = Nothing
    ElseIf m_rst.State < adStateOpen Then
    MsgPopup "Microsoft Excel was unable to request data for " & DATASET_NAME & ": no error information is available", vbCritical + vbOKOnly, "Error requesting " & DATASET_NAME, 60 Set m_rst = Nothing
    Else
    ' Fetch progess is not available with the OLEDB driver I am using ' m_rst_FetchProgress 0, 100, GetStatus(m_rst), m_rst
    End If

    Obviously this is going to be useless if the _FetchComplete event is never raised: 'open' runs asynchronously and the method exits with a recordset in state adStateConnecting or adStateFetching and you're totally reliant on the m_rst_FetchComplete event procedure.

    But this fixes the issue some of the time.

    Next: you need to check that Application.EnableEvents is never set to false when you might have a recordset request out in the ether. I'm guessing that you've thought of that, but it's the only other thing that I can think of.

    Also:

    A tip for readers who are new to ADODB coding: consider using adCmdStoredProc and calling your saved query or your recordset-returning function by name instead of using 'SELECT * FROM' and adCmdText.

    A late answer here, but other people will encounter the same problem.

提交回复
热议问题