VBA DAO.Recordset 在尝试关闭它时为空或未设置 - 但我事先检查它是不是为空
Posted
技术标签:
【中文标题】VBA DAO.Recordset 在尝试关闭它时为空或未设置 - 但我事先检查它是不是为空【英文标题】:VBA DAO.Recordset is null or not set when trying to close it - But I check if its null beforehandVBA DAO.Recordset 在尝试关闭它时为空或未设置 - 但我事先检查它是否为空 【发布时间】:2017-10-15 03:54:18 【问题描述】:在访问应用程序的 VBA 代码中,有一个函数可以将某些数据库字段转换为另一种格式。这发生在 2 个表中,在代码中,您可以通过 2 个循环告诉它们,用于 BOM 和 ROUTING。这段代码的性能很差,因为有时有 200000+ 条记录通过它。为了加快它的速度,我向它添加了交易——它现在的速度是原来的 3 倍。但是,当尝试关闭 ROUTING 记录集时,我收到一条错误消息,提示“对象无效或不再设置”。因此,我在尝试关闭它之前添加了 2 个检查,不是空的,也不是空的。当使用调试器单步执行时,它通过了两项检查,然后尝试关闭记录集,然后转到提供消息的 ErrorHandler。使这个错误更加奇怪的是它在关闭第一个循环的 BOM 记录集时没有问题。 代码:
Public Sub SomeSub()
' set up variables
Dim BOM As DAO.Recordset
Dim ROUTING As DAO.Recordset
Dim Workspace As DAO.Workspace
Set Workspace = DBEngine.Workspaces(0)
' set up errorhandler
On Error GoTo ErrorHandler
' run some process on BOM
Set BOM = CurrentDb.OpenRecordset("some query;", dbOpenDynaset, dbSeeChanges, dbOptimistic)
Workspace.BeginTrans
If Not (BOM.BOF And BOM.EOF) Then
BOM.MoveFirst
Do While (Not BOM.EOF) And (Not BOM.BOF)
' Do some stuff with BOM here
BOM.MoveNext
Loop
End If
Workspace.CommitTrans
BOM.Close
Set BOM = Nothing
Set ROUTING = CurrentDb.OpenRecordset("some query;", dbOpenDynaset, dbSeeChanges, dbOptimistic)
Workspace.BeginTrans
If Not (ROUTING.BOF And ROUTING.EOF) Then
ROUTING.MoveFirst
Do While (Not ROUTING.EOF)
' Do some stuff with ROUTING here
ROUTING.MoveNext
Loop
End If
Workspace.CommitTrans
Workspace.Close
If Not ROUTING Is Nothing Then
If Not ROUTING Is Null Then
ROUTING.Close
End If
End If
GoTo SuccesHandler
ErrorHandler:
MsgBox "Ran into error. Info: " & Err.number & ": " & Err.DESCRIPTION & vbNewLine
Resume SuccesHandler
SuccesHandler:
End Sub
问题: - 为什么会发生这个错误? - null/nothing 检查的正确方法是什么? (显然我这样做的方式不起作用?)
【问题讨论】:
【参考方案1】:您需要先关闭Recordset
,然后再关闭Workspace
。
Workspace.CommitTrans
If Not ROUTING Is Nothing Then
ROUTING.Close
Set ROUTING= Nothing
End If
Workspace.Close
Set Workspace = Nothing
【讨论】:
这行得通。代码现在运行良好,谢谢!我想知道为什么。工作区是否与您在事务中实例化或更新的所有 DAO 记录有关?关闭工作区是否会关闭所有使用所述工作区更新的记录集?【参考方案2】:我会调整该块以匹配有效的块 - 并将工作区处理移出该块:
Set ROUTING = CurrentDb.OpenRecordset("some query;", dbOpenDynaset, dbSeeChanges, dbOptimistic)
Workspace.BeginTrans
If Not (ROUTING.BOF And ROUTING.EOF) Then
ROUTING.MoveFirst
Do While (Not ROUTING.EOF)
' Do some stuff with ROUTING here
ROUTING.MoveNext
Loop
End If
Workspace.CommitTrans
ROUTING.Close
Set ROUTING = Nothing
Set Workspace = Nothing
【讨论】:
这行得通。代码现在运行良好,谢谢!我想知道为什么。工作区是否与您在事务中实例化或更新的所有 DAO 记录有关?关闭工作区是否会关闭所有使用所述工作区更新的记录集? 您不应该关闭当前工作区,就像您从不关闭 CurrentDb 一样。此外,一个常见的规则是始终按照打开对象的相反顺序将对象设置为 Nothing。这在 Access 中很少出现问题,但在 Excel 中可能会导致严重的问题。 所以我应该使用全局定义的工作区,定义方式与 CurrentDB 相同? 是的,这样做。您也可以将CurrentDb
替换为您设置为WorkSpace(0)
的DAO.Database 对象。以上是关于VBA DAO.Recordset 在尝试关闭它时为空或未设置 - 但我事先检查它是不是为空的主要内容,如果未能解决你的问题,请参考以下文章
使用 FindFirst 时出现 DAO RecordSet 错误 3251