1
For an assignment at work, I needed to create a
set of classes that would use ADO to
read from a database.
After using tons of code from ie over the last
few months, I decided I would try to give
something back.
The benefits of using ADO/OLE
DB versus ODBC
are:
-
speed improvements,
-
provider flexibility (if you create a custom
OLE DB
provider, you can use these classes for your
consumer),
-
industry standard for database access, ...
If you're going to be using VB, there is no
reason to not use ADO almost
always because of the way VB provides a very
user friendly interface to ADO.
There is not a user friendly interface available
for ADO with
Visual C++. There
are code examples on MSDN and other sites but
there is no support built into MFC.
Anyone who is familiar with
MFC and
the class wizard, certainly appreciates the help
given when using ODBC
for static binding. Static binding is a quicker
means of reading the database when you will be
reading/updating several rows from a table. For
my purposes, this efficiency was very essential.
These classes and the wizard make doing this a
breeze.
The interface presented with CDatabase
, CRecordset
and CDBVariant
is
very sufficient to perform dynamic binding and
is standard MFC.
I wanted an interface for using ADO that
was basically equivalent to this.
Like all programmers who enjoy code reuse, the
first step for creating this interface was
seeing what was already available. I found two
articles here on here that provided very nearly
exactly what I was after. They are the ADO
classes by Carlos Antollini and the ADO Data
Bound class wizard by Ly Nguyen.
Basically, my work involved integrating these
and providing an interface as similar to CRecordset
and CDatabase
as
possible.
The classes provide all the functionality for
dynamic binding (while also converting to MFC types
from VARIANT
types)
and a very simple interface for static binding.
All the details and exceptions involving ADO and
COM are
encapsulated.
Here is a very simple example of using the
classes with dynamic binding:
Collapse | Copy
Code
// use the jet to read, we know the layout each
// record so we call the getfieldvalues w/
// the pre-known datatypes for the columns.
// CADODatabase db;
//
// BOOL bOpen = db.Open("s:\\tim\\climet.mdb", "Admin",
// "", "Microsoft.Jet.OLEDB.3.51");
// CADORecordset rs(&db);
//
// BOOL bRsOpen = rs.Open("select * from client_dim");
//
// int nRows = rs.GetRecordCount();
//
// int nKey;
// CString strCliNm, strCliDesc;
//
// BOOL fok = TRUE;
//
// fok = rs.GetFieldValue(0, nKey);
// fok = rs.GetFieldValue(1, strCliNm);
// fok = rs.GetFieldValue(2, strCliDesc);
//
// db.Close();
Here is a very simple example of using the
classes with static binding:
First we use the included wizard (Ly Nguyen's
application slightly modified) to generate the
class that derives from both
CADORecordBinding
and
from CADORecordset
:
In later steps, the wizard allows you to specify
a table and the wizard generates the binding
macro calls (ADO_FIXED_LENGTH_ENTRY
,
etc) for you. Of course, you'll have to add the
header to your project file and add the path to
the .dll's
headers in your project settings:
First the CADORecordset
derived
class (the wizard's output):
Collapse | Copy
Code
class CClientPlanRS : public CADORecordBinding, public CADORecordset
{
BEGIN_ADO_BINDING(CClientPlanRS)
ADO_FIXED_LENGTH_ENTRY ( 1,
adInteger, m_lClient_Key, m_ulClient_KeyStatus, TRUE)
ADO_VARIABLE_LENGTH_ENTRY2( 2,
adVarWChar, m_szClient_Name, sizeof(m_szClient_Name),
m_ulClient_NameStatus, TRUE)
ADO_VARIABLE_LENGTH_ENTRY2( 3,
adVarWChar, m_szClient_Description,
sizeof(m_szClient_Description),
m_ulClient_DescriptionStatus, TRUE)
END_ADO_BINDING()
public:
LONG m_lClient_Key;
ULONG m_ulClient_KeyStatus;
CHAR m_szClient_Name[51];
ULONG m_ulClient_NameStatus;
CHAR m_szClient_Description[256];
ULONG m_ulClient_DescriptionStatus;
CClientPlanRS(CADODatabase* pDb, int nCacheSize = -1) :
CADORecordBinding(),
CADORecordset(pDb, nCacheSize)
{ SetRecordBinding(this); }
};
And now using it. We'll use the Microsoft
OLE DB provider for
ODBC, so we don't
have to specify the provider parameter. Also we
will connect using an ODBC
DSN.
Collapse | Copy
Code
// bOpen = db.Open("CLIMET", "TDK2", "NOONHIGH");
//
// CClientPlanRS CliRs(&db);
//
//
// //read table:
// bRsOpen = CliRs.Open("select * from client_dim");
//
// while (!CliRs.IsEOF())
// {
// //do something w/ the records
// CliRs.MoveNext();
// }
//
// //update the first existing row:
// CliRs.MoveFirst();
//
// strcpy(CliRs.m_szClient_id_name, "MAYO999");
// BOOL bUpdate = CliRs.Update();
//
// //add a new row:
// CliRs.m_lClient_id = 999;
// strcpy(CliRs.m_szClient_id_name, "PICKLE");
// strcpy(CliRs.m_szClient_id_desc, "Pickle Inc");
// BOOL bAdd = CliRs.AddNew();
//
It is important to note that these classes do
not throw exceptions. Rather their methods
return BOOL
s.
The code itself if heavily commented so please
review it for further details
ADOLibrary.zip
ADOTestApp.zip
News:
1
UCanCode Advance E-XD++
CAD Drawing and Printing Solution