-
Class ADO - Kết nối SQL Server (Demo)
ongke0711 > 02-06-17, 04:42 PM
Sau khi bạn Dân gợi ý mình nên ngâm cứu chuyển qua lập trình ADO kết hợp với SQL Server (trước giờ chỉ dùng DAO) thì mình cũng đã tìm tòi, sưu tầm, học hỏi…nên cũng bắt đầu nắm được một số cái cơ bản của việc sử dụng thư viện ADO với provider OLEDB để kết nối với SQL server. Bên cạnh đó nó cũng kết nối với nhiều loại CSDL khác.
Nay mình chia sẽ cái Class ADO dùng kết nối với 3 loại CSDL: SQLServer, Access, Excel
- Class này cũng là dạng cơ bản chi có cái tích hợp thêm các chuỗi kết nối tùy từng loại CSDL sẽ đưa ra chuỗi Connection tương ứng. Mình thấy nó cũng phù hợp vì trong 1 ứng dụng thường sẽ có phần lấy dữ liệu từ Excel nên đưa vô sẳn class cho tiện.
- Class có hàm để chạy các Stored Procedure cũng như các câu lệnh SQL.
- Mình có sử dụng kỹ thuật kiểm tra IP của bạn Dân để kiểm tra Server online hay không trước khi chạy kết nối chứ không nó chạy mất mấy phút rồi mới báo lỗi kết nối. Bên cạnh đó cũng kiểm tra đường dẫn OK không đối với kết nối máy trong mạng LAN.
- Tôi dùng CSDL Northwind và các stored proc của nó để test trong demo này. Các bạn chạy file "SQL2000SampleDb.msi" đính kèm trong folder để cài dữ liệu mẫu của Northwind lên SQL Server nhé.
Tuy nhiên có 1 vấn đề này cần các bạn hỗ trợ đó là: mình không truyền được tham số (parameter) dạng ngày\tháng cho store proc trong demo này (stored proc 4, 5 trong demo). Các tham số khác (2, 3 tham số) thì truyền bình thường và chạy tốt. Các bạn kinh nghiệm qua vụ này hướng dẫn sửa giùm nhe. Loay hoay với nó suốt mà làm chưa được.
Cập nhật:
Vụ này mình đã sửa được rồi. Đó là do tên của Stored Procs có khoảng trắng nên nó báo lỗi chứ không phải do tham số truyền vào sai.
Các bạn xem qua và đóng góp ý kiến để học hỏi thêm nhé.
Code cho Class ADO.
Mã PHP:Option Explicit
Private mobjConn As Object 'ADODB.Connection
Private mblnIntegratedSecurity As Boolean
Private mstrModuleName As String 'Dung trong thong bao loi, error trap
Private mstrConnectionString As String
Private mstrCurrentServer As String
Private mstrCurrentDatabase As String
Private mstrDatabaseType As DBaseType
Private mlngRecordCount As Long
Private Const adUseClient As Long = 3
Private Const adLockReadOnly As Long = 1
Private Const adStateOpen As Long = 1
Private Const adCmdStoredProc As Long = 4
Private Const adParamOutput As Long = 2
Private Const adOpenDynamic As Long = 2
Private Const adOpenstatic As Long = 3
Public Enum DBaseType
dbSQLServer = 1
dbAccess = 2
dbExcel = 3
End Enum
Public Enum EditMode
ReadOnly = 0
EditAddDelete = 1
End Enum
Private Sub Class_Initialize()
mstrModuleName = "clsADOConnectDB"
'Set mobjConn = New ADODB.Connection
Set mobjConn = CreateObject("ADODB.Connection")
End Sub
Private Sub Class_Terminate()
On Error Resume Next
mobjConn.Close
Set mobjConn = Nothing
On Error GoTo 0
End Sub
Public Property Get ConnectionString() As String
ConnectionString = mstrConnectionString
End Property
Public Property Let ConnectionString(ByVal NewValue As String)
mstrConnectionString = NewValue
End Property
Public Property Get CommandTimeOut() As Integer
CommandTimeOut = mobjConn.CommandTimeOut
End Property
Public Property Let CommandTimeOut(ByVal NewTimeOut As Integer)
mobjConn.CommandTimeOut = NewTimeOut
End Property
Public Property Get CurrentDatabase() As Integer
'Read-only property
CurrentDatabase = mstrCurrentDatabase
End Property
Public Property Get CurrentServer() As String
'Read-only property
CurrentServer = mstrCurrentServer
End Property
Public Property Get DatabaseType() As DBaseType
DatabaseType = mstrDatabaseType
End Property
Public Property Let DatabaseType(ByVal NewValue As DBaseType)
mstrDatabaseType = NewValue
End Property
Public Property Get IntegratedSecurity() As Boolean
IntegratedSecurity = mblnIntegratedSecurity
End Property
Public Property Let IntegratedSecurity(ByVal NewValue As Boolean)
mblnIntegratedSecurity = NewValue
End Property
Public Sub CloseDB()
'Dong ket noi toi Database
If Not mobjConn Is Nothing Then
If (mobjConn.State And adStateOpen) = adStateOpen Then
mobjConn.Close
Set mobjConn = Nothing
End If
End If
End Sub
Public Function ConnectDB(Optional ByVal DatabaseType As DBaseType = 1, _
Optional ByVal TargetServer As String = "", _
Optional ByVal TargetDatabase As String = "", _
Optional ByVal IntegratedSecurity As Boolean = False) As Boolean
'------------------------------------------------------------------------------------------
'Mo ket noi toi Server và Database chi dinh. Nêu không có tham so thì dùng lai ket noi cu.
'------------------------------------------------------------------------------------------
Dim blnNewConnect As Boolean
Dim blnReturn As Boolean
Dim strDataSource As String
Dim strDB As String
Dim strConn As String
Dim vError As Variant
Dim sErrors As String
blnReturn = True
blnNewConnect = True
On Error GoTo ConnectDBError
If Not mobjConn Is Nothing Then 'Kiem tra xem có Connection chua, có rôi thi dung ket noi cu
If mobjConn.State And adStateOpen = adStateOpen Then '-> Da có ket noi
blnNewConnect = False
End If
End If
If blnNewConnect Then
'Tao ket noi moi
If TargetServer = "" Or TargetDatabase = "" Then
'Neu khong chi dinh ten Server, Database thì dùng lai Connection cu voi tham so cu
If Len(mstrConnectionString) > 0 Then
strConn = mstrConnectionString
Else
'Xay dung chuoi ket noi moi bang hàm BuilConnectionString
strConn = BuildConnectionString(mstrDatabaseType, mstrCurrentServer, _
mstrCurrentDatabase, mblnIntegratedSecurity)
End If
Else
'Xay dung chuoi ket noi moi bang hàm BuilConnectionString voi cac tham so cung cap
strConn = BuildConnectionString(DatabaseType, TargetServer, TargetDatabase, _
mblnIntegratedSecurity)
End If
mobjConn.ConnectionString = strConn
mobjConn.Open
End If
ConnectDBResume:
ConnectDB = blnReturn
Exit Function
ConnectDBError:
blnReturn = False
'ShowErrorMessages Err, mstrModuleName, "ConnectDB"
Select Case Err.Number
Case -2147467259
MsgBoxUni "Thông s" & ChrW(7889) & " k" & ChrW(7871) & "t n" & ChrW(7889) & "i d" & ChrW(7919) & " li" & ChrW(7879) & "u không " & ChrW(273) & "úng.", vbCritical, "Thông báo"
Case -2147217843
MsgBoxUni "Sai tên " & ChrW(273) & ChrW(259) & "ng nh" & ChrW(7853) & "p ho" & ChrW(7863) & "c m" & ChrW(7853) & "t kh" & ChrW(7849) & "u.", vbCritical, "Thông báo"
Case Else
ShowErrorMessages Err, mstrModuleName, "ConnectDB"
End Select
Resume ConnectDBResume
End Function
Public Function BuildConnectionString(ByVal DatabaseType As DBaseType, _
ByVal TargetServer As String, _
ByVal TargetDatabase As String, _
ByVal IntegratedSecurity As Boolean, _
Optional ByVal UserID As String, _
Optional ByVal Password As String) As String
Dim strExt As String 'Extension cua Excel file: xls,xlsx,xlsm,xlsb
'Xay dung chuoi ket noi
Select Case DatabaseType
Case 1 'SQLServer
If Len(UserID) Then 'Có Username/Pass dang nhap
mstrConnectionString = "Network Library=DBMSSOCN;" & _
"PROVIDER=SQLOLEDB;DATA SOURCE=" & TargetServer & _
";INITIAL CATALOG=" & TargetDatabase & _
";User Id=" & UserID & ";Password=" & Password & ";"
Else
'"Provider=SQLNCLI10;"
mstrConnectionString = "Network Library=DBMSSOCN;Provider=SQLOLEDB;" & _
"Server=" & TargetServer & ";" & _
"Database=" & TargetDatabase & ";" & _
"Trusted_Connection=Yes;"
End If
Case 2 'MS Access
Select Case glngAppVersion
Case 10
If Len(Password) Then
mstrConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0;" & _
"Data Source=" & TargetServer & TargetDatabase & ";" & _
"Jet OLEDB:Database Password=" & Password & ";"
Else
mstrConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0;" & _
"Data Source=" & TargetServer & TargetDatabase & ";"
End If
Case Is > 10
If Len(Password) Then
mstrConnectionString = "Provider=Microsoft.ACE.OLEDB.12.0;" & _
"Data Source=" & TargetServer & TargetDatabase & ";" & _
"Jet OLEDB:Database Password=" & Password & ";"
Else
mstrConnectionString = "Provider=Microsoft.ACE.OLEDB.12.0;" & _
"Data Source=" & TargetServer & TargetDatabase & _
";Persist Security Info=False;"
End If
End Select
Case 3 'MS Excel
strExt = UCase(Mid(TargetDatabase, InStrRev(TargetDatabase, ".") + 1))
Select Case strExt
Case "XLSX"
mstrConnectionString = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & TargetDatabase & ";" & _
"Extended Properties = 'Excel 12.0 Xml;HDR=YES'"
Case "XLSB"
mstrConnectionString = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & TargetDatabase & ";" & _
"Extended Properties = 'Excel 12.0;HDR=YES'"
Case "XLSM"
mstrConnectionString = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & TargetDatabase & ";" & _
"Extended Properties = 'Excel 12.0 Macro;HDR=YES'"
Case "XLS"
'to connect Excel 97-2003 from Excel 2007+
mstrConnectionString = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & TargetDatabase & ";" & _
"Extended Properties = 'Excel 8.0;HDR=YES'"
End Select
Case Else
'Truong hop Database khac, tu dieu chinh chuoi ket noi lai cho phu hop
'mstrConnectionString = "Provider=SQLOLEDB;Server=" & TargetServer & _
";Database=" & TargetDatabase & ";Trusted_Connection=yes;"
End Select
mstrCurrentServer = TargetServer
mstrCurrentDatabase = TargetDatabase
mstrDatabaseType = DatabaseType
mblnIntegratedSecurity = IntegratedSecurity
BuildConnectionString = mstrConnectionString
End Function
Public Property Get SQLConnection() As Object 'ADODB.Connection
'Tra ve Conn object.
If Not mobjConn Is Nothing Then
On Error Resume Next
Set SQLConnection = mobjConn
On Error GoTo 0
End If
End Property
Public Function GetRecordset(strSQL As String, Optional EMode As EditMode = 0) As Object 'ADODB.Recordset
Dim objRSet As Object 'ADODB.Recordset
On Error GoTo GRError
mlngRecordCount = 0
If ConnectDB() Then
'Set objRSet = New ADODB.Recordset
Set objRSet = CreateObject("ADODB.Recordset")
objRSet.CursorLocation = adUseClient
objRSet.Open strSQL, mobjConn, adOpenKeyset, adLockOptimistic
mlngRecordCount = objRSet.RecordCount
Set GetRecordset = objRSet
'Ngat ket noi Recorset voi Database - disconnect connection.
Select Case EMode
Case 0 'ReadOnly
objRSet.ActiveConnection = Nothing
Case 1 'EditAddDelete
'Khong dong connection
End Select
End If
GRResume:
CloseDB
Exit Function
GRError:
ShowErrorMessages Err, mstrModuleName, "GetRecordset"
Resume GRResume
End Function
Public Sub ExecuteQuery(SQLToExecute As String, Optional CloseDatabase As Boolean = True)
'Dung de thuc thi cau lenh Select Query SQL
On Error GoTo EAQError
Dim rs As ADODB.Recordset
If ConnectDB() Then
Set rs = mobjConn.Execute(SQLToExecute)
End If
EAQResume:
If CloseDatabase Then CloseDB
Exit Sub
EAQError:
ShowErrorMessages Err, mstrModuleName, "ExecuteActionQuery"
Resume EAQResume
End Sub
Public Function ExecuteActionQuery(SQLToExecute As String, Optional CloseDatabase As Boolean = True) As Boolean
'Dung de thuc thi cau lenh Action Query SQL
Dim blnReturn As Boolean
blnReturn = True
On Error GoTo EAQError
If ConnectDB() Then
mobjConn.Execute SQLToExecute
End If
Exit Function
EAQResume:
On Error Resume Next
If CloseDatabase Or Not blnReturn Then CloseDB
ExecuteActionQuery = blnReturn
Exit Function
EAQError:
blnReturn = False
ShowErrorMessages Err, mstrModuleName, "ExecuteActionQuery"
Resume EAQResume
End Function
Public Function ExecuteSPWithADOCommand(StoredProcName As String, _
OutputParameter As String, OutputValue As Variant, _
ParamArray InputParameters() As Variant) As ADODB.Recordset
'InputParameters: Phai la 1 cap Ten arameter có ký tu @ o dau va Gia tri Para.
'Neu nhieu Param thi cu viet noi tiep thanh tung cap, cách nhay dau phay.
'OutputParmeter cung them ky tu @ o dau.
Dim objCmd As ADODB.Command
Dim rsCmd As ADODB.Recordset
Dim intParam As Integer
'Dim recordsAffected As Long
On Error GoTo ESPError
If ConnectDB() Then
Set objCmd = New ADODB.Command
With objCmd
.ActiveConnection = mobjConn
.CommandText = StoredProcName
.CommandType = adCmdStoredProc
.Parameters.Refresh
'Lay tham so
For intParam = 0 To UBound(InputParameters) Step 2
.Parameters(InputParameters(intParam)).Value = _
InputParameters(intParam + 1)
Debug.Print InputParameters(intParam) & "-" & InputParameters(intParam + 1)
Next intParam
'Xac dinh co tham so Output khong
If Len(Trim(OutputParameter)) > 0 Then
.Parameters(OutputParameter).Direction = adParamOutput
End If
'.Execute
Set rsCmd = New ADODB.Recordset
rsCmd.Open .Execute(recordsAffected)
End With
Set ExecuteSPWithADOCommand = rsCmd
'Lay gia tri cho Output Para
If Len(Trim(OutputParameter)) > 0 Then
OutputValue = objCmd.Parameters(OutputParameter).Value
Else
OutputValue = vbNullString
End If
Else
'Neu bi mat ket noi nhung khong bi loi phat sinh
OutputValue = vbNullString
Set ExecuteSPWithADOCommand = Nothing
End If
Exit Function
ESPResume:
On Error Resume Next
Set ExecuteSPWithADOCommand = Nothing
Set objCmd = Nothing
CloseDB
Exit Function
ESPError:
ShowErrorMessages Err, mstrModuleName, "ExecuteSPWithADOCommand"
Resume ESPResume
End Function
Public Sub ShowErrorMessages(ByVal StandardErrorObject As VBA.ErrObject, _
ByVal SourceModule As String, ByVal SourceMethod As String)
'Su dung cho bay loi cua class.
Dim strMsg As String
'Loi co ban cua he thong.
If StandardErrorObject.Number <> 0 Then
strMsg = "Error: " & CStr(Err.Number) & vbCrLf & vbCrLf & "Description: " & _
Err.Description & vbCrLf & vbCrLf
End If
strMsg = strMsg & SourceModule & "::" & SourceMethod & vbCrLf
Err.Clear
MsgBoxUni strMsg, vbCritical, "Liên h" & ChrW(7879) & " ng" & ChrW(432) & ChrW(7901) & "i qu" & ChrW(7843) & "n tr" & ChrW(7883) & " ch" & ChrW(432) & ChrW(417) & "ng trình " & ChrW(273) & ChrW(7875) & " tr" & ChrW(7907) & " giúp"
End Sub
Link file: http://www.mediafire.com/file/b28rf1vflx...O_Demo.rar -
RE: Class ADO - Kết nối SQL Server (Demo)
maidinhdan > 03-06-17, 01:30 AM
Có rất nhiều ý kiến: Từ từ sẽ góp sau. Vì em đang bận, chắc tầm tuần sau mới góp cụ thể được.
Ban đầu thì anh xem lại Chuỗi kết nối Provider trước đã.
Máy em chạy không được rồi đấy. -
RE: Class ADO - Kết nối SQL Server (Demo)
ongke0711 > 03-06-17, 12:06 PM
-
RE: Class ADO - Kết nối SQL Server (Demo)
hieuvn > 03-06-17, 06:07 PM
Bạn cần sủa lại methode ExecuteSPWithADOCommand
1, Tham số nhập vào thường là adParamInput, hiếm khi nào lấy tham số ra nên bỏ bớt cho khỏi rối
2,Tạo thêm 1 function con để lấy Param input Type vì để như bạn khi nhập tham số thường nhập input Type vào, mà nguyên cái ParramArray() đã dài lê thê rồi dẫn đến ngô khoai lẫn lộn cả !
về storedProcedure: không nên có khoảng trống trong tên (mình xem qua có 2 sp có khoảng trống)
kết nối: mới test kết nối qua SQL Server : OK kết nối tốt
về reference: add Microsoft ActiveX Data Object 2.8 Library, mình thấy bạn dùng late binding rồi nhưng chưa triệt để thì phải vì nếu không add thư viện này vẫn báo lỗi.
sơ qua vài nét vậy, có thời gian mình sẽ cùng ngâm cứu. Have fun -
RE: Class ADO - Kết nối SQL Server (Demo)
ongke0711 > 04-06-17, 10:01 AM
(03-06-17, 06:07 PM)hieuvn Đã viết: 2,Tạo thêm 1 function con để lấy Param input Type vì để như bạn khi nhập tham số thường nhập input Type vào, mà nguyên cái ParramArray() đã dài lê thê rồi dẫn đến ngô khoai lẫn lộn cả !
Hiện tại tôi dùng ParamArray nên buộc khai báo biến kiểu Variant hết và cũng không khai báo Input Type cho từng Parameter chi khai báo Para name và Value khi đưa vào method "ExecuteSPWithADOCommand".
Bạn đề xuất dùng cái hàm con để xử lý nhiều parameters thì mình chưa hiểu lắm. Ý bạn tạo 1 array có đủ 3 tham số :Name, Type, Value rồi dùng For... Next để Add Parameter? Nếu bạn có làm qua hướng dẫn giùm nhé. Cảm ơn. -
RE: Class ADO - Kết nối SQL Server (Demo)
hieuvn > 04-06-17, 04:46 PM
(04-06-17, 10:01 AM)ongke0711 Đã viết: Hiện tại tôi dùng ParamArray nên buộc khai báo biến kiểu Variant hết và cũng không khai báo Input Type cho từng Parameter chi khai báo Para name và Value khi đưa vào method "ExecuteSPWithADOCommand".
Bạn đề xuất dùng cái hàm con để xử lý nhiều parameters thì mình chưa hiểu lắm. Ý bạn tạo 1 array có đủ 3 tham số :Name, Type, Value rồi dùng For... Next để Add Parameter? Nếu bạn có làm qua hướng dẫn giùm nhé. Cảm ơn.
mình có dùng qua rồi nhưng vì không dùng nhiều nên không tạo function mà dùng trực tiếp trên form luôn cho tiện với lại mình đã chuyển qua dùng .net rồi nên không ngâm cứu ado nữa.
chủ nhật đang rảnh mần luôn cho bạn cái function layType như sau:
Mã:Private Function layType(ByVal thamso As Variant) As ADODB.Parameter
Dim result As New ADODB.Parameter
Dim direction As ADODB.ParameterDirectionEnum
direction = adParamInput
result.direction = direction
Select Case TypeName(thamso)
Case "String"
result.Type = adVarChar
result.Size = Len(CStr(thamso))
result.value = CStr(thamso)
Case "Integer"
result.Type = adInteger
result.value = CLng(thamso)
Case "Double"
result.Type = adDouble
result.value = CDbl(thamso)
End Select
Set layType = result
End Function
và tất nhiên mình mạn phép sửa lại toàn bộ code của bạn Function ExcuteSPWithADOCommand:
và trên form phát biểu như sau:Mã:Public Function ExecuteSPWithADOCommand(StoredProcName As String, _
ParamArray InputParameters()) As ADODB.Recordset
Dim objCmd As ADODB.Command
On Error Resume Next
If ConnectDB() Then
Set objCmd = New ADODB.Command
With objCmd
.ActiveConnection = mobjConn
.CommandText = StoredProcName
.CommandType = adCmdStoredProc
Dim i As Integer
Dim value As Variant
For i = LBound(InputParameters) To UBound(InputParameters)
value = InputParameters(i)
.Parameters.Append layType(value)
Next
Set ExecuteSPWithADOCommand = .Execute
End With
End If
End Function
case 4
Mã:Set rs = gobjDB_sql.ExecuteSPWithADOCommand("" & lstProcs.Column(1) & "", "" & Me.txtStart & "", "" & Me.txtEnd & "")
Have fun -
RE: Class ADO - Kết nối SQL Server (Demo)
ongke0711 > 04-06-17, 06:58 PM
Cảm ơn bạn hieuvn. Tôi đã sửa theo hướng dẫn của bạn và đã chạy tốt rồi.
Thay đổi một số điểm như sau:
- Bỏ khoảng trắng trong tên của Stored Procs.
- Bổ sung chút trong hàm LayType là thêm trường hợp "Date"
...
Case "Date"
result.Type = adDate
result.value = CDate(thamso)
.....
- Câu lệnh thực thi thì bỏ dấu nháy kép cho tham số ngày.
Mã PHP:Set rs = gobjDB_sql.ExecuteSPWithADOCommand("" & lstProcs.Column(1) & "", Me.txtStart, Me.txtEnd)
-
RE: Class ADO - Kết nối SQL Server (Demo)
tieu_ngao > 11-06-17, 12:17 PM
Thấy hay quá nhưng chưa hiểu, vì mới nghiên cứu access thôi. Nếu có thể Ongke0711 hướng dẫn từng bước để làm kết nối được ko?