The motivation behind building a COM object for ADO (which is already a COM object) is to generalize and package all of the routines and objects involving ADO that are useful in my solutions. In Chapter One of the ADO Programmer’s Guide, Microsoft writes, “ADO is designed to provide developers with a powerful, logical object model for programmatically accessing, editing and updating a wide variety of data sources through OLE DB system interfaces.” Where we see “wide variety” suggesting that ADO is extremely general. My solutions require a finite number of generic routines that are a subset of the total number of features ADO provides. The routines are:
The remainder of this document will list and describe the properties and methods of this object, explore a few real world cases where this object is implemented, and look toward future enhancements.
The file name is rasxADO.dll, containing the Class ADOServices.
Public Properties of ADOServices | |
|---|---|
Connection | Get an ADODB.Connection object. This property is read only. |
ErrorText | Get both the VBA error and the Collection of ADO error numbers and descriptions. This property is read only. |
RecordsAffected | Get the number of data records affected by procedures/SQL executed by this Object. Usually this value is -1 since it is poorly supported by the OLE DB providers used by this Class. (See StoredProcCmd() below.) This property is read only. |
SessionLog | Get verbose descriptions of ADO connection/disconnection attempts, procedure/SQL execution and Class initialization/termination. Recommended for debugging purposes. This property is read only. |
Public Methods of ADOServices | |
|---|---|
ClientRst() | Returns a disconnected, ADO Recordset (CursorType:=adOpenStatic and LockType:=adLockBatchOptimistic), optimized for “fat-client” grid controls like those for VB 6 x forms. This method is also used to access ADO Recordset methods like MoveFirst() and MovePrevious(), and properties like Recordcount. |
CloseRecordset() | Closes the specified Recordset object and sets the object to Nothing. |
CnnCmd() | Executes dynamic SQL commands against the ADODB.Connection object. |
CnnRst() | Executes dynamic SQL projections against the ADODB.Connection object and returns a read-only, forward-only ADO Recordset. |
Connect() | Returns a Boolean value indicating success/failure while attempting to set the Connection property of this Class. This method must be used before any other methods in this Class. |
Disconnect() | Closes the ADO connection object. |
StoredProcCmd() | Executes a stored procedure against the ADODB.Command object. |
StoredProcRst() | Executes a stored procedure against the ADODB.Command object and returns a read-only, forward-only ADO Recordset. |
The arguments forClientRst(),CnnCmd(), andCnnRst() are identical. The following table summarizes:
Arguments of ClientRst(), CnnCmd(), and CnnRst() | |
|---|---|
Source | Required. String literal. By value. Valid SQL for the DBMS. SQL strings with parameters contain question marks (?). |
Options | Required. ADODB.CommandTypeEnum. By value. As of this writing, adCmdStoredProc is not supported by these methods: ClientRst(), CnnCmd(), and CnnRst(). Only adCmdText has been extensively tested. |
SQLPrms | Optional. Variant. By value. This value can be an array or delimited string literal corresponding to the parameters required by Source. The string literal must be delimited by vbNullChar characters. |
Two of the arguments for Connect() has its own Enumerated Constants. The following table summarizes:
Arguments of Connect() | |
|---|---|
DataSrc | Required. String literal. By value. When DataSrcType is not set to adUDL then this contains the server name of the data source. When DataSrcType:=adUDL then this contains the path to the Microsoft Data Link file. |
DataSrcType | Required. The Enumerated Constants for this class are: adJetOLEDB = 0& adJet4OLEDB = 1& adODBCOLEDB = 2& adOracleOLEDB = 3& adSQL7OLEDB = 4& adSybaseOLEDB = 5& adUDL = 6& When this class is used in ASP-based solutions these constants should be specified in an Include File. |
ConnectType | Required. The Enumerated Constants for this class are: adConnectAsynchronous = 16& adConnectSynchronous = -1& The value |
Catalog | Optional. String literal. By value. Usually specifies the name of the database. |
UserName | Optional. String literal. By value. Usually specifies the name of the database user with permission to access the data.* |
Password | Optional. String literal. By value. Usually specifies the password of the database user with permission to access the data.* |
*By omitting the UserName and Password when calling Connect() for SQL Server 7.x (or MSDE 1.x) on Windows NT/2000, ADOServices will use the NT/2000 login credentials to attempt to connect to the database server.
The arguments forStoredProcCmd(), andStoredProcRst() are identical. The following table summarizes:
Arguments of StoredProcCmd(), and StoredProcRst() | |
|---|---|
StoredProcName | Required. String literal. By value. Contains the name of the stored procedure of the DBMS supported by this Class. |
Params | Optional. String literal. By reference. This value can be an array or delimited string literal corresponding to the parameters required by When The 2D parameter array has the following form: , etc. |
Has2DparamArray | Optional. Boolean. By value. Indicates if Params contains a two-dimensional array. See Params. |
TimeOut | Optional. Number. By value. The number of seconds to set the CommandTimeout property of the ADO Command object. By default it is set to 30 seconds. |
The function basGetKeyString() is used to retrieve string literals from a remote database. These miscellaneous strings are stored in a single table with columns name, caption and string. This function attempts to eliminate the need to “hard-code” strings into a code Module that is “globally” accessible. This function calls the stored procedure GetKeyString:
Private Function basGetKeyString(ByVal KeyName As String, _
Optional ByVal ColumnName = "string") As String
Dim objADO As rasxADO.ADOServices
Dim objRst As ADODB.Recordset
On Error GoTo basGetKeyString_Err
basGetKeyString = vbNullString
Set objADO = VBA.CreateObject("rasxADO.ADOServices")
If objADO.Connect(dbSERVER, adSQL7OLEDB, _
adConnectSynchronous, dbCATALOG, dbUSER) Then _
Set objRst = objADO.StoredProcRst("GetKeyString", KeyName)
If objRst.BOF And objRst.EOF Then
'Recordset with 0 rows.
Call Me.basAppInfoMsg("KeyName """ _
& KeyName & """ returns no records.")
Else
basGetKeyString = objRst.Fields(ColumnName) & vbNullString
End If
Else
GoTo basGetKeyString_Err
End If
basGetKeyString_Exit:
Call objADO.CloseRecordset(objRst)
objADO.Disconnect
Set objADO = Nothing
Exit Function
basGetKeyString_Err:
If (VBA.Err.Number <> 0) Or (objADO.Connection.Errors.Count > 0) Then
Call Me.basDataErrMsg(objADO, "basGetKeyString()")
If (VBA.Err.Number <> 0) Then
Resume basGetKeyString_Exit
Else
GoTo basGetKeyString_Exit
End If
End If
End Function
The subroutine basFavoritesScan() is one of three functions used to generate an HTML page out the Internet Explorer Favorites stored on a local machine. This function illustrates the use of two-dimensional parameter passed to the stored procedure NewFavorite:
Private Sub basFavoritesScan(ByRef objADO As rasxADO.ADOServices, _
Optional ByVal Directory = "\")
Dim objFolders As Scripting.Folders
Dim objFolder As Scripting.Folder
Dim objFiles As Scripting.Files
Dim objFile As Scripting.File
Dim lngFolderCount As Long
Dim varParameters(0 To 1, 0 To 1) As Variant
'To be a two-dimensional array of form:
' ,
' ,
' ,
' ,
'etc.
'For readability:
varParameters(0, 0) = "@path"
varParameters(1, 0) = vbNullString
varParameters(0, 1) = "@url"
varParameters(1, 1) = vbNullString
On Error GoTo basFavoritesScan_Err
p_strInFile = basGetKeyString("path_root_favorites") & Directory
Set objFolders = p_objFileSys.GetFolder(p_strInFile).SubFolders
'Initialize Progress Bar.
Call basProgress(0, 0, objFolders.Count): p_lngStatusCount = 0
For Each objFolder In objFolders
varParameters(1, 0) = Directory & objFolder.Name
varParameters(1, 1) = "Directory"
If Not(objADO.StoredProcCmd("NewFavorite", varParameters, True)) _
Then GoTo basFavoritesScan_Err
Set objFiles = objFolder.Files
For Each objFile In objFiles
varParameters(1, 0) = Directory _
& objFolder.Name & "\" & objFile.Name
varParameters(1, 1) = "File"
If Not(objADO.StoredProcCmd("NewFavorite", _
varParameters, True)) _
Then GoTo basFavoritesScan_Err
Next
'Mark progress.
p_lngStatusCount = p_lngStatusCount + 1
Call basProgress(p_lngStatusCount)
Next
'Terminate Progress Bar.
Call basProgress(0): p_lngStatusCount = 0
basFavoritesScan_Exit:
Exit Sub
basFavoritesScan_Err:
If (VBA.Err.Number <> 0) Or (p_objADO.Connection.Errors.Count > 0) Then
Call Me.basDataErrMsg(p_objADO, "basFavorites()")
If (VBA.Err.Number <> 0) Then
Resume basFavoritesScan_Exit
Else
GoTo basFavoritesScan_Exit
End If
End If
End Sub
The functionality of this COM object is directly related to the needs of the Solutions that inspired its creation. It follows that these proposed future enhancements primarily anticipate future demands that may be. What “may be” could be:
Recognizing ADOX. The Microsoft Access 2000 Project File (.ADP) is certainly using ADOX to support the UI. It is possible that one can “outgrow” what Microsoft is already offering through its use of ADOX in Access 2000. It may be prudent to prepare for that day. Chapter 15 of the ADO Programmer’s Guide, “ADOX Fundamentals” is a good start.
Recognizing ADO MD. Support for multidimensional data providers via ADO appears to be limited to OLE DB providers to Microsoft systems. However, exploring the issue for a few minutes can’t hurt. Mike Gunderloy’s Advanced Data Shaping article for Smart Access get right into the thick of it.
Recognizing XML. Paul Enfield’s Using Server-Side XSL for Early Rendering: Generating Frequently Accessed Data-Driven Web Pages in Advance seems to take ADO out of picture when he shows us an XML world. However, ADO 2.6 can be used to open XML files into an ADO Recordset and can even remind me of a really clunky in-memory database. The most compelling treatment of this subject comes from Don Box, his Using ADO to Create XML-based Recordsets, which had me seriously considering using the ADO schema.1
Recognizing ADO.NET. Having seen the simplified object model in ADO.NET it is possible that my class will not be needed in .NET projects. This remains to be seen.
| Download | Description |
|---|---|
| rasxADO.zip | Compiled DLL and associated library files. |
1 The main thing that stopped me in my tracks was the amount of security permissions I would have to give the anonymous access account of IIS in order to persist ADO XML files. The problem is that the file can’t be saved twice: my code would have to delete the file first before saving a new one from memory. Not good. Curiously, the “save method” of the MSXML 4.x DOM object does not have this problem.