Read an Excerpt
Chapter 5: The OLE DB Consumer
In this chapter, we'll be taking a more in depth look OLE DB consumers, and in particular, using the OLE DB consumer templates. After a brief run through the consumer template classes in Visual C++, we'll have a go at a practical example that uses them to access some data. First, we'll step through the code that the ATL Object Wizard generates, and see how much of the hard work is done for us, and then we'll add some new code to customize the application for our needs.What is an OLE DB Consumer?
In the last chapter, we discussed OLE DB and the ideas behind it in some depth, and introduced the concept of OLE DB consumers. An OLE DB consumer is simply an application that uses OLE DB COM objects and the OLE DB provider in order to access data. An OLE DB consumer works by calling the methods on the OLE DB COM interfaces implemented by the OLE DB provider.
An OLE DB consumer can be an application (as our example will demonstrate) that uses an OLE DB provider to access its data, but this isn't the only definition. One can even define the ADO objects as OLE DB consumers, in that they use OLE DB objects to provide database services.
The OLE DB Consumer Templates
In this section, we'll be looking at the OLE DB Consumer Templates. These are an important addition to VC 6.0, and they make using OLE DB a much more straightforward process for the C++ programmer.
What are the Consumer Templates?
Directly implementing OLE DB consumers is hard work. As we saw in the last chapter, OLE DB objects can implement many interfaces. Thus, Microsoft saw a need to put a wrapper around OLE DB that would makeusing OLE DB objects easier, but without a full layer of code, such as ADO. Hence, Visual C++ 6.0 introduced the OLE DB consumer templates and the associated wizard. Instead of directly accessing OLE DB objects, one simply uses these wrapper classes, which are based on ATL classes, as well as related macros in order to take advantage of OLE DB functionality.
If you are unfamiliar with ATL please see Appendix B for a brief overview. You could also check out one of the ATL references listed in Appendix A.
The main thing that these wrapper classes do is to combine a number of OLE DB interfaces into one class. Yet, they do not require the overhead of ADO.
As we will see, these template classes can be mapped to similar functionality in ODBC and DAO. As with recordsets, the wizard actually generates the classes, which we can then incorporate into our application. Changes can be made to these classes to control how we access the data.
The OLE DB Consumer Classes
In this section, we'll take a quick look at the main consumer classes that implement the OLE DB interfaces. In particular, we'll be looking at:
CDataSource
CSession
CTable
CCommand
Accessor classes
CRowset
CDataSource
This is the wrapper class around the data source object specified by OLE DB. Its purpose is to connect to the database through an OLE DB provider - in effect, it represents a connection to the database. A CDataSource object takes input such as the location of the data source and the authentication information, which is needed to log on to the data source.
CSession
Each session object creates a single access session to the database. From this session, it is possible to create a rowset or command object and thus access the data in the database. We can also create tables and indexes though the session object. Sessions allow for transactions. Multiple sessions can be created for each data source - you might want do this when you need to separate transactions in the same application.
CTable and CCommand
CTable and CCommand are classes that allow us to access rowsets. CTable is specified as follows:
template class TAccessor = CNoAccessor, class TRowset = CRowset
class CTable : public CAccessorRowset TAccessor, TRowset
CCommand is specified as follows:
template class TAccessor = CNoAccessor, class TRowset = CRowset,
class TMultiple = CNoMultipleResults>
class CCommand :
public CAccessorRowset TAccessor, TRowset,
public CCommandBase,
public TMultiple
The various classes parameterizing CTable and CComand are:
TAccessor - an accessor class. The default is CNoAccessor. (We'll look at accessor classes a little later in this section).
TRowset - a rowset class. The default is CRowset.
TMultiple - this class can be either CMultipleResults if the class is to return multiple rowsets, or the default, CNoMultipleResults.
CTable is generally used for simple rowsets, where no parameters are specified and no multiple results are necessary. The OLE DB consumer wizard (part of the ATL object wizard) will allow you to specify either a command or a table object.
If one selects a command (an SQL select statement in the RDBMS world), then the CCommand class is used. This has the advantage of flexibility. Once you use the wizard to create a command based on one table, it can later be modified to handle a more complex query. This, as we will see later on in the chapter, is the means by which we'll create a command object using a query that includes more than one table.
Accessor Classes
In writing an OLE DB consumer application, one important task is creating the accessor that will be bound to the CCommand or CTable object. Recall from the last chapter that the accessor is the object that binds the data from the database to the member variables in the command or table object in the consumer application. Thus it determines how the data looks to the client application....