【问题标题】:Trouble Appending Records to MS Access ADO Recordset - The Records Disappear无法将记录附加到 MS Access ADO 记录集 - 记录消失
【发布时间】:2015-07-10 23:23:20
【问题描述】:

使用 MS Access 2013:

我正在创建一个分离的 ADO 记录集,作为我正在编写的应用程序的内存写入缓冲区。通常我会使用表/查询,但多人同时使用数据库。如果我将这些记录写到表中,用户就有可能会覆盖彼此的数据。

ADODB.recordset 被定义为一个全局变量,并使用一个函数进行初始化。现在,这是棘手的部分。我可以很好地定义记录集,但是当我添加第一条记录时,添加后记录“消失”。

我使用 While-Wend 循环来添加记录。当我进入该循环的中间时,我可以移动到不同的记录,并 debug.print 任何我喜欢的值。但是当我退出循环的那一刻,我失去了所有的记录。无论我移动到哪里,任何 debug.print 命令都会产生“无当前记录”。当我在其他函数中调用全局变量时,我得到一个空记录集。

代码如下:

Option Compare Database
'Establish a global recordset variable to be a write buffer
Public gbl_rstADO_WriteBuffer As ADODB.Recordset
Option Explicit

Private Function InitWriteBuffer()
Dim strSQL As String
Dim dbs As DAO.Database
Dim rst As DAO.Recordset
Dim i As Integer
Dim j As Integer

'These records will form the structure and initial entries of the write buffer
strSQL = "SELECT [#DEFAULT MASTER QUERY].* FROM [#DEFAULT MASTER QUERY] INNER JOIN " & _
"tblBatchCircuitUploadTable ON [#DEFAULT MASTER QUERY].[Install ID] = " & _
"tblBatchCircuitUploadTable.[Install ID] WHERE (((tblBatchCircuitUploadTable.[Install ID]) Is Not Null));"

Set dbs = CurrentDb
Set rst = dbs.OpenRecordset(strSQL)


Set gbl_rstADO_WriteBuffer = New ADODB.Recordset

'Create detatched recordset using fields from SQL query
For i = 0 To rst.Fields.Count - 1
    gbl_rstADO_WriteBuffer.Fields.Append rst.Fields(i).Name, adVariant, , adFldMayBeNull
Next

With gbl_rstADO_WriteBuffer
    .CursorType = adOpenKeyset
    .CursorLocation = adUseClient
    .LockType = adLockPessimistic
    .Open
End With


rst.MoveFirst

'Copy values from DAO recordset, one-by-one, into the detatched ADO recordset
While Not rst.EOF
    gbl_rstADO_WriteBuffer.AddNew

    'Move through values of current source record, and copy one by one to ADO destination
    For j = 0 To gbl_rstADO_WriteBuffer.Fields.Count - 1
        gbl_rstADO_WriteBuffer.Fields(j).Value = rst.Fields(j)
    Next

    gbl_rstADO_WriteBuffer.Update
    rst.MoveNext
Wend

    'With the following command I receive a "No Current Record" error
    'Moving to first, last, etc in the immediate window all still produce "no current record"
    Debug.Print gbl_rstADO_WriteBuffer.Fields(0).Value



'Cleanup
Set rst = Nothing
Set dbs = Nothing

End Function

有人看到我遗漏的东西吗?

【问题讨论】:

  • 根据Append Method (ADO)"ADO 不支持以下数据类型,并且不应在将新字段附加到记录集对象 (ADO) 时使用:adIDispatch、adIUnknown、adVariant。”
  • 我认为这是一个过程,而不是一个编程问题。为什么不使用一个临时表来快照您的数据集而无需用户交互?为什么不让应用程序在运行时调用 ADO 或 ODBC 记录集,而不是在后端数据库中保存内存?最后,考虑保存recordset externally
  • "通常我会使用一个表/查询,但是多个人同时使用数据库。如果我将这些记录写到一个表中,用户可能会覆盖彼此的数据。” - 如果您正确设置了多用户访问应用程序,则不会。每个用户必须拥有自己的前端(用户界面)本地副本,因此如果应用程序写入前端 .accdb/.accde 文件中的本地表,那么用户将 永远不能覆盖彼此的数据。

标签: ms-access vba ado ms-access-2013


【解决方案1】:

非常感谢您的反馈!所有的点都非常好。

在技术方面,HansUp 给出了答案:事实证明,您不能将 adVariant 数据类型附加到 ADO 记录集中。不支持。跛脚。

因此,如果您倾向于将 DAO 记录集中的记录复制到 ADO 记录集中以分离它,那么有一种巧妙的方法可以将数据类型从一个映射到另一个创建 ADO 记录集。

这是我想出的:

...
For i = 0 To rst.Fields.Count - 1
    intDataType = IDS_MapToTypeADO(rst.Fields(i).Type)
    If intDataType = adVarWChar Then
        gbl_rstADO_WriteBuffer.Fields.Append rst.Fields(i).Name, intDataType, 50, adFldMayBeNull
    Else
        gbl_rstADO_WriteBuffer.Fields.Append rst.Fields(i).Name, intDataType, , adFldMayBeNull
    End If
Next

With gbl_rstADO_WriteBuffer
    .CursorType = adOpenKeyset
    .CursorLocation = adUseClient
    .LockType = adLockPessimistic
    .Open
End With
...

Private Function IDS_MapToTypeADO(iTypeDB As Integer) As Long

Select Case iTypeDB

    'Fixed width adWChar does not exist
    Case dbText: IDS_MapToTypeADO = adVarWChar
    Case dbMemo: IDS_MapToTypeADO = adLongVarWChar
    Case dbByte: IDS_MapToTypeADO = adUnsignedTinyInt
    Case dbInteger: IDS_MapToTypeADO = adSmallInt
    Case dbLong: IDS_MapToTypeADO = adInteger
    Case dbSingle: IDS_MapToTypeADO = adSingle
    Case dbDouble: IDS_MapToTypeADO = adDouble
    Case dbGUID: IDS_MapToTypeADO = adGUID
    Case dbDecimal: IDS_MapToTypeADO = adNumeric
    Case dbDate: IDS_MapToTypeADO = adDate
    Case dbCurrency: IDS_MapToTypeADO = adCurrency
    Case dbBoolean: IDS_MapToTypeADO = adBoolean
    Case dbLongBinary: IDS_MapToTypeADO = adLongVarBinary
    Case dbBinary: IDS_MapToTypeADO = adVarBinary
    Case Else: IDS_MapToTypeADO = adVarWChar

End Select

End Function

这里借鉴了另一个 StackOverflow 解决方案: Converting DAO Recordset to Disconnected ADO Recordset dbDecimal Issue

再次感谢您。我很感激!

【讨论】:

  • 很高兴您解决了您的问题。但如果我不恳求您在这里转换您的数据处理过程,那将是失职。像 Access 这样的数据库不应该向应用程序发出数据请求,而是相反。数据库必须存在并且与任何客户端分离。抽象前端和后端流程很重要。这种调用内存中的外部记录集虽然很简洁,但可能是对 CPU 资源的低效使用。考虑在运行时将您的应用直接连接到实时临时表数据源。祝你好运!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-11-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多