在VBA中传递记录集对象销毁

时间:2014-07-17 18:43:19

标签: excel-vba recordset destroy excel-2013 vba

我想我已经理解了记录集的传递。它总是通过引用传递。我有一个问题是对象的破坏。

我有一个从Access获取记录集的函数。我从给定的例程中调用该函数,将SQL语句传递给它并从中获取记录集结果。请参阅下面的代码示例。

在调用例程结束时,我关闭记录集并将对象设置为Nothing。我不清楚的是,是否需要做些什么来销毁被调用函数中的记录集对象。由于记录集是通过ByRef传递的,我倾向于认为关闭记录集并将其设置为Nothing也不会从调用例程中将其破坏。还有,我的一部分认为被调用函数中的局部变量在函数完成时被破坏,但我意识到自动销毁的变量与对象不同,即使在当地也必须手动销毁。

所以问题是,我是否必须以某种方式销毁函数记录集对象,或者在调用例程结束时销毁记录集对象是否会破坏这两个实例?使用下面的代码示例,当rstSample被破坏时,GetReadOnlyRecords记录集是否会被破坏,或者我是否还必须做其他事情来销毁它?

我要问的另一个原因是,除了我已经知道上述事实之外,还有另外一个函数我也称之为GetReadOnlyRecords函数,但我实际上并不需要记录。 (参见:私有函数ChkDataNew()As Boolean)。在那里我只需要知道结果记录集是否包含任何记录,所以不是在调用函数中创建记录集的实例,而是简单地说"如果GetReadOnlyRecords(strSQL).RecordCount> 0那么"。因此,在这种情况下,我没有在调用函数中销毁记录集,这表明在GetReadOnlyRecords函数中没有任何内容关闭/设置为无原始记录集。显然我可以将记录集引入到调用函数中,但它似乎没有必要,因为我可以在" If"中获得我需要的所有信息。声明。因此,如果从调用函数中销毁记录集会在被调用函数中销毁它,那么我是否需要在调用函数中创建一个记录集,这样我就可以销毁它,即使我不需要它呢? / p>

Option Explicit

    'create a module-level, Public reference to a Connection object
    Public objConn As ADODB.Connection

    'create a string constant with the dB path
    Private Const strDBPath As String = "C:\MyPath.accdb"

    Private Const strConString = "Provider=Microsoft.ACE.OLEDB.12.0;" & _
                "Data Source=" & strDBPath & ";" & _
                "Persist Security Info=False;"

Public Sub OpenDB()
    'create a new instance of the Connection object
    Set objConn = New ADODB.Connection
    objConn.Open strConString
End Sub

Public Sub CloseDB()
    objConn.Close
    Set objConn = Nothing
End Sub

Public Function GetReadOnlyRecords(strSQL As String) As Recordset

    'this routine presumes the Database already has an Open Connection
    'we can't risk possibly opening it twice

    Dim rstTMP As ADODB.Recordset

    Set rstTMP = New ADODB.Recordset
    rstTMP.Open strSQL, objConn, adOpenStatic, adLockReadOnly, adCmdText
    Set GetReadOnlyRecords = rstTMP

End Function

Private Sub UpdateData() 

    Dim rstSample As ADODB.Recordset
    Set rstSample = New ADODB.Recordset

    OpenDB
        strSQL = "SELECT * FROM tblExample"
        Set rstSample = GetReadOnlyRecords(strSQL)

        rstSample.DoStuff

        'Destroy the Recordset object
        rstDrawings.Close
        Set rstDrawings = Nothing
    CloseDB

End Sub

Private Function ChkDataNew() As Boolean

    Dim dtNewDate As Date
    Dim strSQL As String

    ChkDataNew = False
    Set dtNewDate = wsMySheet.Range("QDate").Value
    strSQL = "SELECT tblExample.[Date] FROM tblExample WHERE tblExample.[Date] = " & dtNewDate

    OpenDB
        If GetReadOnlyRecords(strSQL).RecordCount > 0 Then
            ChkDataNew = True
        End If
    CloseDB

End Function

1 个答案:

答案 0 :(得分:1)

将对象引用设置为Nothing时,您实际上只是“断开”引用,而不是(直接)影响引用的对象。只要存在至少一个指向它的引用,就会保留引用的对象:当没有剩余的引用时,它将被自动垃圾收集(尽管可能不是立即收集)。

函数完成后,函数中的任何记录集引用都将超出范围(假设它们是局部变量而不是Globals),因此您不必担心这些。

从技术上讲,在退出方法之前,您不需要将对象引用设置为Nothing:但是一些程序员认为它是“良好实践”。

关于“关闭”MS说:

  

使用Close方法关闭Recordset,Record或Stream对象   发布相关数据以及您可能拥有的任何独占访问权限   通过这个特定的对象来获取数据。你以后可以打电话给   Open方法用相同或修改的方法重新打开对象,   属性。

     

当Recordset对象关闭时,调用任何需要的方法   实时光标会生成错误。

因此,关闭记录集不会导致对它的任何引用不起作用:例如,您仍然可以调用Open,但是其他方法(例如)MoveNext会引发错误记录集已关闭。

http://msdn.microsoft.com/en-us/library/windows/desktop/ms675814(v=vs.85).aspx

相关问题