Much ADO About Something — or Other

Well, every single article I’ve come across about ADO starts with the words “Much ADO”, so why make an exception? I’m pretty certain, by the way, that the reason for this is simply to establish that the author of the article knows the name of at least one Shakespearean play. Besides, “Timon of Athens” wouldn’t really make much sense. Yeah, I know the names of two Shakespeare plays.

One of the key goals of programming is to make everything look the same as everything else. After all, only a programmer would try to convince people that a 3½” floppy disk was really the same thing as a 32Gbyte hard disk. In every physical respect (apart from the fact that they both use magnetism to store information) they’re completely different. But they look the same to you and me, don’t they, because their drivers hide the differences from us.

The same holds at higher levels, too. In the last chapter, we saw how the isolation layer in the ADSI components enabled us to write an application that talked in the same way to both a conventional Windows NT directory and an LDAP-oriented one. We’re going to look at something now that does the same trick for databases.

ADO is the latest in a long series of Microsoft Data access technologies, and it effectively supersedes the old Data Access Objects (DAO) and Remote Data Objects (RDO) objects. This is where it sits in the Microsoft Universal Data Access hierarchy:

So, from the top down, we have our application that either talks directly to OLE DB or via ADO. ADO talks to OLE DB. Databases either present themselves as OLE DB providers or via ODBC drivers, which in turn presents itself as an OLE DB provider.

We could easily spend an entire chapter looking at ADO, but it’s really outside the scope of this book. Instead, we’ll proceed on a kind of “need to know” basis, and pick up enough to put together a simple application. To be honest, once you’ve got started on ADO, it’s pretty intuitive. You’ll probably find that you can easily explore further yourself, without any interfering authors breathing down your neck.

As our vehicle for exploring ADO, we’re going to develop

DBManager
, the database management program that will be used by Player 1 in the Kidnap Game. In some ways, VB would be the perfect vehicle for developing this, as ADO objects are fully automation compliant and fit very well with VB. However, we’re going to be accessing the database from one of our ATL components later on, so we’d better get used to using Visual C++. So our application is going to be written using MFC. It’s dialog-based, and here’s the form:

In order to develop against ADO, we’ll need to include a couple of header files in both

DBManager.cpp
and
DBManagerDlg.cpp
adoid.h
and
adoint.h
. We’ll also need to add the library
adoid.lib
to the list of libraries with which we link.

As I've noted in the code, I've used ADO 1.5, that comes with MTS 2.0. This is the same as the one included in the OLEDB SDK from Microsoft. The version that comes with Visual C++ has a different number of parameters (three not four) for the

ADOConnection::Open()
method. I've therefore put the MTS include and library files first in the listings on the Tools | Options Directory tab.

There are seven objects in the ADO object model. I’d like to concentrate first of all on the

Connection
,
Recordset
and
Field
objects.

A

Connection
object, not surprisingly, represents a connection to a database. For our purposes, the key methods are
Open()
, which opens up a
Recordset
,
Close()
, which closes one, and
Execute()
, which executes a command.

So what’s a

Recordset
? A
Recordset
is a collection of records. This collection may be the result of a database query (perhaps implemented by a command passed to the
Execute()
method of a
Connection
object), or it may simply represent the entire contents of a table.

A

Recordset
is the most important object in ADO, because this is the object on which you carry out all the manipulations. For example, you can add a new record to it using the
AddNew()
method, you can delete one or more records using the
Delete()
method, and you can navigate through it using the various
Move()
methods. Not surprisingly, fields in records from a
Recordset
are represented by
Field
objects.

You can do a lot with just these three objects. More complex provider-specific commands can be implemented using a

Command
object, perhaps in tandem with a
Parameter
object. Provider-specific properties of a
Connection
,
Command
,
Recordset
or
Field
object can be manipulated using a
Property
object. Finally, errors can be determined via an
Error
object.

The only unfortunate aspect of ADO is that it’s optimized for OLE automation, so it’s chock full of

VARIANT
s, which are a real pain as far as C++ is concerned. Anyway, we’re halfway through the chapter already and we haven’t done any coding, so let’s take a look at ADO as we dig into our DBManager application.

© 1998 by Wrox Press. All rights reserved.