ADO记录集按顺序传递给多个函数时会丢失其数据(Access VBA)

最后发布: 2011-11-07 17:00:05


问题

我有一个返回ADO记录集的函数,而该记录集又用于提供后续函数。 第一次将其传递给其中一个函数时,它运行良好; 但是在下一个函数中,记录集位于EOF。 我以为我的记录集是By Ref传递的,所以尝试使用MoveFirst :这给我一个错误,因为游标类型默认为仅向前。

我尝试了以下方法:

  • 将其设置为By Val ; 这没有效果。
  • 创建记录集的副本,并在第一个函数中使用原始记录,在第二个函数中使用该复制记录; 仍然是同样的问题(第二种说法是EOF,这意味着它是空的而不是EOF;我无法想象两个记录集以某种方式连接在一起,但是也许)。
  • 将我的数据库代码更改为使用其他游标类型( adOpenStatic ):实际上,这对于我的应用程序更正确,但结果却很奇怪。 也就是说,在更改之前,在更改之后,工作正常的查询未返回第一个字段! 这很重要,因此我无法继续这条路。

有任何想法吗?


数据库主要查询功能: GetData 获取SQL和varchar参数列表(如果有)并返回记录集。 它引用dbOpen ,它只是使用提供的凭据打开连接。

Private Function GetData(ODBC As DBConnection, ByVal QuerySQL As String, Optional Parameters As Collection) As ADODB.Recordset
    Dim DB As ADODB.Connection
    Dim Query As ADODB.Command
    Dim Parameter As ADODB.Parameter

    Set DB = New ADODB.Connection

    If dbOpen(DB, ODBC) Then
        Set Query = New ADODB.Command
        Query.ActiveConnection = DB
        Query.CommandText = QuerySQL

        If Not Parameters Is Nothing Then
            For Each param In Parameters
                Set Parameter = Query.CreateParameter(, adVarChar, adParamInput, Len(param), param)
                Query.Parameters.Append Parameter
            Next
            Set Parameter = Nothing
        End If

        Set GetData = Query.Execute

        ' Uncommenting this seems to reset the data in GetData...
        ' A bit of a memory leak, but we assume VBA will take care of it :P
        'dbClose DB
    Else
        MsgBox "Cannot connect to the database.", vbExclamation
        Set GetData = Nothing
    End If
End Function

然后我做这样的事情:

Dim myRecords as ADODB.Recordset

' For the sake of argument, we assume this returns a nontrivial recordset
Set myRecords = GetData(someDSN, someSQL, someParameters)

Debug.Print myRecords.EOF ' Returns False

ID = writeHeader(myRecords)

Debug.Print myRecords.EOF ' Returns True

writeData ID, myRecords   ' Breaks because at EOF

writeHeader函数将使用MoveNext遍历记录集中的每个记录。 但是,如果我按值或作为副本传递myRecords ,则仍然会遇到EOF问题。 如果我添加MoveFirst在记录迭代代码结尾writeHeader ,它会抱怨,我不能移动到这样一个记录的开始。 如果我更改GetData函数,以便Set GetData = Query.Execute更改为:

Set GetData = New ADODB.Recordset

GetData.CursorType = adOpenStatic
GetData.Open Query

然后,当运行我的代码中的查询时-尚未更改-第一个字段不是记录集的一部分(!?)说,例如, myRecords!ID是第一个字段:如果引用了此字段,我将收到一条警告,指出该项目不是记录的成员(或者它也不是枚举的成员;因此myRecords.Fields(1)仅返回查询中的下一个字段)。

oracle vba ado
回答

通过@TimWilliams的有用技巧,我通过将GetData函数更改为以下内容来解决了这个问题:

Private Function GetData(ODBC As DBConnection, ByVal QuerySQL As String, Optional Parameters As Collection) As ADODB.Recordset
    Dim DB As ADODB.Connection
    Dim Query As ADODB.Command
    Dim Parameter As ADODB.Parameter
    Dim Output As ADODB.Recordset

    Set DB = New ADODB.Connection

    If dbOpen(DB, ODBC) Then
        Set Query = New ADODB.Command
        Query.ActiveConnection = DB
        Query.CommandText = QuerySQL

        If Not Parameters Is Nothing Then
            For Each param In Parameters
                Set Parameter = Query.CreateParameter(, adVarChar, adParamInput, Len(param), param)
                Query.Parameters.Append Parameter
            Next
            Set Parameter = Nothing
        End If

        Set Output = New ADODB.Recordset
        Output.CursorType = adOpenStatic
        Output.CursorLocation = adUseClient
        Output.Open Query
    Else
        MsgBox "Cannot connect to the database.", vbExclamation
        Set Output = Nothing
    End If

    Set GetData = Output
End Function

然后,在游历记录集之前,我使用MoveFirst