检查ADODB连接是否打开

问题描述 投票:18回答:3

我在一些excel过程中使用以下内容来建立与我们数据库的连接。

Private Const strConn As String = _
    "PROVIDER=SQLOLEDB.1 ..."     

Sub OpenConnection()

Set cn = CreateObject("ADODB.Connection")
cn.Open strConn
cn.CommandTimeout = 0
Set rs = CreateObject("ADODB.Recordset")
Set rs.ActiveConnection = cn

End Sub 

在后续代码中,我使用各种SQL字符串打开连接。我想测试rs是否打开,所以我知道它需要关闭,但以下操作无效。如何更改以下条件才能工作?

If (rs.Open = True) Then
    rs.Close
End If

以下内容有效,但我宁愿不以这种方式使用错误捕获:

On Error Resume Next
    rs.Close
vba oledb
3个回答
34
投票

ADO Recordset具有.State属性,可以检查其值为adStateClosed还是adStateOpen

If Not (rs Is Nothing) Then
  If (rs.State And adStateOpen) = adStateOpen Then rs.Close
  Set rs = Nothing
End If

MSDN about State property

编辑;不检查1或0的原因是.State的原因是,即使它在99.99%的时间内工作,仍可能具有other flags set,这将导致If语句无法通过adStateOpen检查。

Edit2:

对于未引用ActiveX数据对象的后期绑定,您几乎没有选择。使用ObjectStateEnum

中的adStateOpen常量的值
If Not (rs Is Nothing) Then
  If (rs.State And 1) = 1 Then rs.Close
  Set rs = Nothing
End If

或者您可以自己定义常量以使代码更具可读性(为一个很好的示例将它们全部定义。)

Const adStateClosed As Long = 0 'Indicates that the object is closed.
Const adStateOpen As Long = 1 'Indicates that the object is open.
Const adStateConnecting As Long = 2 'Indicates that the object is connecting.
Const adStateExecuting As Long = 4 'Indicates that the object is executing a command.
Const adStateFetching As Long = 8 'Indicates that the rows of the object are being retrieved.    

[...]

If Not (rs Is Nothing) Then

    ' ex. If (0001 And 0001) = 0001 (only open flag) -> true
    ' ex. If (1001 And 0001) = 0001 (open and retrieve) -> true
    '    This second example means it is open, but its value is not 1
    '    and If rs.State = 1 -> false, even though it is open
    If (rs.State And adStateOpen) = adStateOpen Then 
        rs.Close
    End If

    Set rs = Nothing
End If

1
投票

这个话题很老,但是如果像我这样的人在寻找解决方案,这就是我找到的解决方案:

Public Function DBStats() As Boolean
    On Error GoTo errorHandler
        If Not IsNull(myBase.Version) Then 
            DBStats = True
        End If
        Exit Function
    errorHandler:
        DBStats = False  
End Function

所以“ myBase”是一个数据库对象,我已经制作了一个类来访问数据库(带有插入,更新等的类……),并且在模块上该类在对象中使用了声明(显然),我可以进行测试与“ [对象] .DBStats”的连接:

Dim BaseAccess As New myClass
BaseAccess.DBOpen 'I open connection
Debug.Print BaseAccess.DBStats ' I test and that tell me true
BaseAccess.DBClose ' I close the connection
Debug.Print BaseAccess.DBStats ' I test and tell me false

编辑:在DBOpen中,我使用“ OpenDatabase”,在DBClose中,我使用“ .Close”和“ set myBase = none”编辑2:在函数中,如果您未连接,.version会给您一个错误,因此,如果您未连接,则errorHandler会给您提供false


0
投票

这是一个古老的话题,但万一其他人还在找...

我在停靠事件后遇到麻烦。即使重新连接到网络,保存在全局对象中的打开的数据库连接也会出错。这是由于TCP连接被远程主机强行终止。 (错误-2147467259:TCP提供程序:远程主机强行关闭了现有连接。)

但是,错误只会在尝试第一个事务后显示。到目前为止,Connection.State和Connection.Version(根据上述解决方案)都不会显示任何错误。

所以我在下面写了一个小的sub来强制执行错误-希望它有用。

在我的设置(Access 2016,SQL Svr 2008R2)上的性能测试每个电话大约1毫秒。

函数adoIsConnected(adoCn作为ADODB.Connection)作为布尔值

'---------------------------------------------------------------- '#PURPOSE: Checks whether the supplied db connection is alive and hasn't had it's TCP connection forcibly closed by remote host, for example '#RETURNS: True if the db is connected, false otherwise '#AUTHOR: Belladonna '---------------------------------------------------------------- Dim i As Long 'Run a simple query, to test the connection On Error Resume Next i = adoCn.Execute("SELECT 1").Fields(0) On Error GoTo 0 'If i is 1, all is well If i = 1 Then adoIsConnected = True Else adoIsConnected = False End If End Function

© www.soinside.com 2019 - 2024. All rights reserved.