2013-07-12 205 views
14

我在一些excel過程中使用以下內容來建立與我們數據庫的連接。檢查ADODB連接是否打開

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 

回答

25

ADO記錄集具有.State屬性,你可以檢查它的值是adStateClosedadStateOpen

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

MSDN about State property

編輯; 不對.State進行1或0檢查的原因是因爲即使它工作的時間爲99.99%,仍有可能產生other flags set這將導致If語句未通過adStateOpen檢查。

EDIT2:

後期綁定的,而不引用的ActiveX數據對象,你有幾種選擇。 從ObjectStateEnum

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

使用adStateOpen常量的值,也可以定義常量自己使你的代碼更易讀(定義他們都爲一個很好的例子。)

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 
+0

好吧 - 只是猜測,但是在答案中有錯字嗎? ...讓我試着編輯...它應該讀取'If(rs.State And rs.adStateOpen)= rs.adStateOpen Then':儘管我仍然不明白這個條件語句。如果rs是開放的,它將評估什麼? '如果(1和?)=?然後' – whytheq

+0

它是按位運算。只有在'.State'中的那個位被設置並且所有其他位都被清零時,'adStateOpen'位纔會保持置位狀態。如果在「.State」中設置了該位標誌,則將'And'操作值與'adStateOpen'進行比較的結果只會導致爲'真'。 – Raybarg

+0

嘿,你的困惑很可能已經到位了。我不是故意使用'rs.adStateOpen',而是'adStateOpen'。 – Raybarg

0

這個主題是老但如果其他人跟我一樣尋找一個解決方案,這是我找到了解決辦法:

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」是一個數據庫對象,I H ave創建了一個類來訪問數據庫(插入,更新等類),並在模塊上使用類聲明在一個對象中(很明顯),我可以用「[Object] .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」和‘設置myBase =什麼’ 編輯2:在功能,如果您無法連接,.version給你一個錯誤,所以如果沒有連接,錯誤處理器給你錯誤

+0

這是什麼:'.Version'? ....你是否可以在'myClass'內添加代碼....我最近發佈了這個,就在這一週,所以我會非常感興趣的看看你是如何編寫'myClass':http:// codereview。 stackexchange.com/questions/116253/class-module-to-wrap-up-classic-ado-call-to-sql-server – whytheq

+0

「.Version」爲您提供數據庫的版本,因此如果您未連接到數據庫(我使用Access)你不能通過這種方式知道版本,你可以知道你是否連接到數據庫 – JustGuest