A Set of MFC Wrapper Classes for ADO - Version 2.20J






4.94/5 (10 votes)
This is an alternative for "A set of ADO classes - version 2.20"
- Download ado2jrevA.zip containing the updated classes - 16.4 KB
- Download msado60_Backcompat_i386.zip compatibility file - 23.1 KB
Introduction
This is a small update I made to the excellent set of ADO classes by Carlos Antollini. Though this might be a little less common than .NET classes, MFC is still very much in use and I hope the changes would be useful to someone.
Background
Dated back to 2005, the original classes did not account for 64 bit data and compilers. I have taken the liberty to add support for 64 bit data such as MS-SQL BIGINT
. I also have support for 64 bit binary data to 64 int conversion useful in situations where we must read MS-SQL ROWVERSION and similar type fields.
I have also added a handful of utility functions to make common tasks part of the classes. I did however kept the original code in place for the most part and insured to keep backward compatibility.
Of course, all of this is meant to be compiled as a 32 bit application. I might add more for 64 bit applications later, if necessary.
You might also have to get a new TLB for some operating system. It is included in this article and from Microsoft. (msado60_Backcompat_i386.tlb)
Using the Code
In this section, I will not repeat what Carlos described in detail in his original post but concentrate on my changes.
Tweaking the Header for the Host Operating System
Depending on the bit size of the host operating system, a different version of ADO is used. Make sure to define this value before including the header if needed:
#define _USE_WINX86_FOLDER_ //Use this when compiling on 64 bit PC
#include <ado2.h> //ADO wrapper class
New Stuff
First, support 64 bit data:
The GetFieldValue
functions returns a value that contains the value of a field.
BOOL GetFieldValue(LPCTSTR lpFieldName, INT64& lValue);
BOOL GetFieldValue(int nIndex, INT64& lValue);
BOOL GetFieldValue(LPCTSTR lpFieldName, UINT64& ulValue);
BOOL GetFieldValue(int nIndex, UINT64& ulValue);
The SetFieldValue
functions sets the value of a field.
BOOL SetFieldValue(int nIndex, INT64 lValue);
BOOL SetFieldValue(LPCTSTR lpFieldName, INT64 lValue);
BOOL SetFieldValue(int nIndex, UINT64 lValue);
BOOL SetFieldValue(LPCTSTR lpFieldName, UINT64 lValue);
New Utility Functions
Here are my new utility functions that wrap commonly used tasks.
The CADODatabase
class has a set of functions that correspond to the _ConnectionPtr
. To this class, I have added these:
bool supIsValidDBPtr
- Returnstrue
if the object is initialized and is ready to be used- On a new pointer
(CADODatabase* pDB)
,pDB->supIsValidDBPtr()
should returnfalse
- On a new initialized pointer
(pDB = new CADODatabase)
,pDB->supIsValidDBPtr()
should returntrue
- On a new pointer
bool supReopenDB
- Tries to close and reopen a database, making a test to insure connectivity with a "SELECT 1
" recordsetbool supIsDBAccessible
- Test to see if the current DB object can be accessed and optionally test with a "SELECT 1
" recordset or try reopen
The CADORecordset
class has a set of functions that corresponds to the _RecordsetPtr
. To this class, I have added these:
- 64 bit support
bool supHasRecord()
- Simple way to check if the last query returned any rowsbool supOpenHasRecord()
- Combines theOpen
method and the above in a single call__int64 supDbRowVersionTo64(LPCSTR pszField)
- Returns a 64 bit representation of an SQL Server ROWVERSION field or similar type data
The new CADOTool
class has a set of static utility functions that wraps common tasks:
CADODatabase* pDB = NULL; //Declare a new empty pointer
bool bRc = supInitDatabase(&pDB, szConnectString, 10); //Try to init
bool supInitDatabase
- Accepts a pointer to a pointer, tries to open the connection and then initialize the host's pointer to an initializedCADODatabase
objectvoid supCloseDB
- Accepts a pointer to a pointer and safely closes the database and release resourcessupCloseDB(&pData->m_pAltDB); //Closes the database if opened and the pointer is valid, //set the host's pointer to NULL on exit
bool supIsValidDBPtr
- Tests the passedCADODatabase
pointer to see if it is allocated and valid on a best effortbool supIsValidRSPtr
- Tests the passedCADORecordset
pointer to see if it is allocated and valid on a best effortvoid supCleanCMD
,void supCleanRS
, andvoid supCleanPrm
all releases appropriate resources and set the host's pointer to NULL.bool adoBuildConnection
- Displays the ADO conenction wizard UI and sets the composed connection string in the passedCString
if success or return false if cancelled or error.
Sample
This sample tries to demonstrate basic usage of the classes with a fictitious database.
CString csConnect;
CString csSQL;
CADODatabase* pDB = NULL; //Important, set to NULL!!
CADORecordset* pRS = NULL; //Important, set to NULL!!
int iUpdated;
//Fields
__int64 iID;
CString csName;
COleDateTime cdtBirth;
BOOL bActive;
//Build a connect string
if(!CADOTool::adoBuildConnection(csConnect))
{
OutputDebugString("You cancelled the dialog!\n");
return;
}
//Open the database
if(!CADOTool::supInitDatabase(&pDB, csConnect))
{
OutputDebugString("Somehow, the database cannot be opened!\n");
return;
}
//Get some data with this made-up query
csSQL = "SELECT ID, fldName, fldBirth, fldIsActive FROM tblUserData ORDER BY fldMemberDate DESC";
//Use ADO...
try{
if(pRS->supOpenHasRecord(csSQL)) //If we have some data
{
//We are on the first record
do
{
pRS->GetFieldValue("ID", iID);
pRS->GetFieldValue("fldName", csName);
pRS->GetFieldValue("fldBirth", cdtBirth);
pRS->GetFieldValue("fldIsActive", bActive);
//Do something with the data
//Edit something!
pRS->Edit();
pRS->SetFieldValue("fldIsActive", true);
pRS->Update();
pRS->MoveNext(); //Move! Otherwise be caught in an infinite loop!
}while(!pRS->IsEOF());
}
else
{
//What!? Either cannot open or we don't have data
if(pRS->IsOpen())
{
//Add new record
pRS->AddNew();
pRS->SetFieldValue("fldName", CString("First, Last"));
pRS->SetFieldValue("fldBirth", COleDateTime(1980, 10, 2, 0, 0, 0));
pRS->SetFieldValue("fldIsActive", TRUE);
pRS->Update();
pRS->GetFieldValue("ID", iID); //Get our newly created ID
}
}
//Now, let us try a direct query to our fictitious DB
if(pDB->Execute("UPDATE tblManager SET fldLastChech = GETDATE() WHERE ID = 3"))
{
iUpdated = pDB->GetRecordsAffected(); //Get affected records by last query
}
}
catch(CADOException& cEx)
{
OutputDebugString("Oups, got a database error!\n");
OutputDebugString(cEx.GetErrorMessage());
OutputDebugString("\n");
}
//No matter what, clean all!
CADOTool::supCleanRS(&pRS); //Clean resources from our recordset
CADOTool::supCloseDB(&pDB); //Release our DB
History
- 7th May, 2013 - First release of my contributed code to the original 2.20
- 15th May, 2013 - Added example and fixed a function error (
supOpenHasRecord
)