2013-07-12 39 views
14

Tôi sử dụng các thao tác sau từ trong một số quy trình excel để thiết lập kết nối với cơ sở dữ liệu của chúng tôi.Kiểm tra xem kết nối ADODB có đang mở không

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 

Trong mã tiếp theo, tôi mở kết nối bằng nhiều chuỗi SQL khác nhau.
Tôi muốn thử nghiệm nếu rs mở để tôi biết rằng nó cần phải đóng nhưng những điều sau không hoạt động. Làm thế nào tôi có thể thay đổi điều kiện trong những điều sau đây để làm việc?

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

Các công trình sau đây nhưng tôi không muốn sử dụng lỗi bẫy theo cách này:

On Error Resume Next 
    rs.Close 

Trả lời

25

ADO Recordset có .State thuộc tính, bạn có thể kiểm tra xem giá trị của nó là adStateClosed hoặc 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

Chỉnh sửa; Lý do không kiểm tra .State với 1 hoặc 0 là bởi vì ngay cả khi nó hoạt động 99,99% thời gian, vẫn có thể có other flags set điều này sẽ làm cho câu lệnh If thất bại trong việc kiểm tra adStateOpen.

Chỉnh sửa2:

Đối với ràng buộc trễ mà không có đối tượng dữ liệu ActiveX được tham chiếu, bạn có vài tùy chọn. Sử dụng các giá trị của adStateOpen liên tục từ ObjectStateEnum

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

Hoặc bạn có thể xác định hằng số cho mình để làm cho mã của bạn dễ đọc hơn (định nghĩa chúng tất cả cho một ví dụ điển hình.)

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

ok - chỉ cần đoán nhưng có lỗi chính tả trong câu trả lời không? ... hãy để tôi cố gắng chỉnh sửa ... nó nên đọc 'Nếu (rs.State Và rs.adStateOpen) = rs.adStateOpen Sau đó': mặc dù tôi vẫn không hiểu điều này tuyên bố có điều kiện. Nó sẽ được đánh giá như thế nào nếu rs được mở? 'Nếu (1 Và?) =? Sau đó, – whytheq

+0

Đó là thao tác bit và ''. Bit đó là 'adStateOpen' sẽ chỉ được thiết lập nếu bit đó trong' .State' được thiết lập và tất cả các bit khác đều bằng không. Kết quả so sánh giá trị hoạt động 'và' với' adStateOpen' sẽ chỉ kết quả 'True' nếu cờ bit đó được đặt trong' .State'. – Raybarg

+0

Heh, sự nhầm lẫn của bạn có lẽ đã xảy ra. Tôi không có ý định sử dụng 'rs.adStateOpen' nhưng' adStateOpen'. – Raybarg

0

Chủ đề này là cũ nhưng nếu những người khác như tôi tìm kiếm giải pháp, đây là giải pháp mà tôi đã tìm thấy:

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 

Vì vậy "myBase" là đối tượng cơ sở dữ liệu, tôi h ave đã tạo một lớp để truy cập vào cơ sở dữ liệu (lớp có chèn, cập nhật, vv ...) và trên mô-đun mà lớp đó sử dụng khai báo trong một đối tượng (rõ ràng) và tôi có thể kiểm tra kết nối với "[đối tượng] .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 

chỉnh sửa: trong DBOpen tôi sử dụng "OpenDatabase" và trong DBClose tôi sử dụng ".Close" và 'thiết lập MyBase = không có gì' chỉnh sửa 2: trong chức năng, nếu bạn không kết nối, .version cung cấp cho bạn một lỗi vì vậy nếu không kết nối, errorHandler cung cấp cho bạn false

+0

Đây là gì: '.Phiên bản'? .... có thể bạn có thể thêm mã bên trong 'myClass' .... Gần đây tôi đã đăng bài này, chỉ một tuần khác, vì vậy tôi sẽ rất quan tâm để xem cách bạn đã viết' myClass': http: // codereview. stackexchange.com/questions/116253/class-module-to-wrap-up-classic-ado-call-to-sql-server – whytheq

+0

".Phiên bản" cung cấp cho bạn phiên bản của Cơ sở dữ liệu vì vậy nếu bạn không kết nối với cơ sở dữ liệu (Tôi sử dụng Access), bạn không thể biết phiên bản như vậy bằng cách này bạn có thể biết nếu bạn đang kết nối với cơ sở dữ liệu – JustGuest

Các vấn đề liên quan