C++Builder Data Modules are the fundamental basis for implementing the nonvisual side of your C++ Builder application. This chapter covers the fundamentals and stylistic elements of using Data Modules in your implementations. The C++Builder Data Module Designer does for data modules what the Form Designer does for visual forms—it enables you to place, select, modify, delete, and edit components in data modules. But what are data modules, and how are they useful?
What Are Data Modules?
Data modules enable you to separate access to your data (and to nonvisual components) from the user interface presented by your forms. This offers an extremely powerful and visually oriented way to create the nonvisual portions of your systems, especially when coupled with the C++Builder capabilities provided by form inheritance. A data module is a special kind of form, with its own form designer. Any nonvisual component can be dropped into a data module from the Component Palette. Most often, these are database-oriented components such as TTable, Tquery, and TDataSource, but the data module is not limited to those components. Components such as TTimer and TActionList are also frequently found in data modules. You can add data modules to the Object Repository, just like forms, and you can copy or inherit from the data modules you put in the repository—also just like forms.
Borland Database Component Types
This section offers an overview of the component sets offered by Borland for database applications.
Borland provides a variety of component sets for accessing databases.
• BDE—The Borland Database Engine components are the original component set provided for Borland products. It connects programs with the Borland Database Engine and its database drivers. The BDE provides a common abstraction layer across a variety of database anagement systems (DBMS) (for more information on these components, see Chapter 8, “The Borland Database Engine.”)
• Interbase Express (IBExpress)—Components very similar to the BDE component set, which are optimized for Borland’s Open Source DBMS—Interbase, and which don’t require the BDE to be installed on the client system (for more information on these components, see Chapter 10, “Interbase Express Component Overview.”)
• dbExpress—A lightweight component set with lightweight drivers for widely used client-server databases—no BDE required. (for more nformation on these components, see Chapter 12, “Data Access with dbExpress.”)
• dbGo—A component set known as ADO Express prior to C++Builder 6. These components provide an interface to Microsoft’s ActiveX Data Objects database drivers (usually referred to as providers). Although dbGo doesn’t need the BDE, it also cannot be run under Linux, and, therefore, shouldn’t be used in CLX applications. (for more information on these components, see Chapter 11, “ADO Express Components for C++Builder.”)
Database components are only as good as their user interface counterparts. Almost every conventional user interface component has a “data aware” counterpart, which can be hooked to a TDataSource. TDataSource components can connect to TDataSet descendants, which, for all of the component sets, are the basic data access components they provide. Figure 6.1 shows the relationships between these major component subsets in the UML (Unified Modeling Language) notation.
ADO Express Components for C++Builder
ADO stands for ActiveX Database Objects. ADO is Microsoft’s replacement for the ODBC (the Open Database Connectivity) standard and earlier data access technologies, such as DAO and RDO. ADO is a COM (Component Object Model) API (Application Programming Interface) that replaces the C language-based ODBC API and makes it easier to use object-oriented techniques with databases even in lowlevel programming. The ADO components hide most of the complexity of dealing with the COM aspects of ADO behind an interface much like that of normal Borland VCL database components. In addition, they allow data from ADO to be used in normal VCL data-aware controls, such as grids, edit boxes, and charts. This is possible because the ADO components descend from TDataSet, and because TDataSource can work with any TDataSet descendant.
ADO can work with any database that has an ODBC driver. In addition, ADO offers support for data stored in nonrelational forms, such as XML (the successor to HTML) or email message stores, so long as there is a data provider that conforms to ADO standards. In theory, you can issue SQL against any ADO data, but there might be specialized forms of SQL needed to access nonrelational data. ADO is a capable technology that offers complete access to almost every database in use. This chapter shows how the dbGo components provide you with the ability to access every feature of ADO, through an interface similar to the powerful framework Borland established for use with the BDE components.
ADO Versus BDE
There has always been a market for non-BDE components to be used with VCL programs in Delphi and C++Builder. There are a number of reasons for this. First, the BDE, rightly or wrongly, is perceived as being slow for some applications. Second, the memory and disk footprint of the BDE is thought by some to be larger than they prefer. Finally, even with installation programs such as Wise and InstallShield to
reduce the complexity of installing the BDE, it has remained complex to ensure a safe BDE installation/upgrade, especially for releases of the BDE occurring between releases of the installer.
Prior to ADO, most component sets targeted either specific DBMS, such as dBase or InterBase, or database technologies, such as ODBC. Others implemented their own replacements for the BDE. However, they all had a problem—their components had a unique interface that was not the same as that offered by the BDE-oriented components. This made it harder to change an application back to the BDE if that was
desired. Unfortunately, the ADO components share this drawback.
ADO has several other drawbacks in comparison to the BDE. For one, it requires an explicit connection string that names a provider, server, and database, which makes it more difficult to provide easy retargeting of ADO components to other databases or DBMS without code changes. Secondly, unlike the BDE, SQL in ADO components cannot be used to heterogeneously join tables across databases within the same DBMS or across different DBMS.
One caution with the ADO components is that they do not eliminate the need to worry about revisions of the underlying libraries—in this case, the ADO objects and the facilities needed by the database you are using (such as the Jet database engine
required by Access). Given all this, what are the advantages of the ADO components?
• Much of their supporting software is delivered with the operating system, so you do not have to deploy it.
• With driver development for the BDE somewhat slower than previous versions (though the BDE can use newer ODBC drivers, and those will continue to keep pace with DBMS development for some time), ADO can be your ticket to access unusual or advanced data technologies such as XML.
• The ADO components can ease the transition from Microsoft tools, such as Visual C++ to C++Builder.
436 CHAPTER 11 ADO Express Components for C++Builder
• TADOQuery components are always editable without recourse to cached updates, UpdateSQL, or the complex conditions that allow a successful RequestLive.
Note that a form of cached update (called batch update) is available for ADO components.
• The ADO components allow for SQL to be executed asynchronously and for monitoring the progress of commands through event handlers. This can also be used to provide the highly desirable progress meter to show how much of a query or command operation is complete.
• Unlike the BDE components, it is fairly safe to halt a database program using Program Reset (this usually provokes an out of memory error from the BDE on the next run)—however, when it is not safe, it usually takes your system down
• Finally, though you should conceal as much of the “ADOness” of the ADO components from your programs as you can, familiarity with the concepts of ADO can be useful for future employment or projects where management mandates the use of ADO.
The following list describes each of the ADOExpress components found on the ADO tab of the Component Palette. It is important to learn about the components in an Component Overview 437 order that makes sense. In this case, we will cover the components in an order that
both eases your transition from the BDE components (by showing the similar components in ADOExpress first), and which also reflects the dependencies between the components. Thus, we will first cover the TADOConnection component (used by all other ADO components), followed by TADOTable and TADOQuery (both similar to their BDE counterparts TTable and TQuery), and only then will we move on to the more unusual components, such as TADODataSet and TADOCommand.
• TADOConnection Connects to the database, manages transactions; it is essentially equivalent to TDatabase. Note that there is no TSession equivalent for the ADO components. Some TSession capabilities are present in TADOConnection.
• TRDSConnection Connects to a database in such a way that allows multitier access to an ADO recordset. Only usable with TADODataSet; supports the Microsoft Remote Data Space facility, which enables an ADO recordset to be passed across tiers of a multitier database application. Note that this is not the same as MIDAS support for Remote Data Modules.
• TADOTable Accesses a single database table name by table name; essentially equivalent to TTable.
• TADOQuery Accesses one or more tables in a single database using SQL commands. Can perform any SQL including SELECT, INSERT, DELETE, ALTER TABLE, and so on; essentially equivalent to TQuery.
• TADOStoredProc Executes a stored procedure from a particular database; essentially equivalent to TstoredProc.
• TADODataSet Essentially the same as TADOQuery, except that you cannot execute SQL that does not return a result set.
• TADOCommand Essentially the same as TADOQuery. You can execute any SQL with TADOCommand, but to access the resultset, you need to provide a separate TADODataset that will be connected to the command’s result set.
Connecting to the database is necessary so that the components can reach out through the driver to the actual database. Until a connection is made, no access to the database is possible.
The TADOConnection Class
This class takes the place of a combination of TSession and TDatabase and is generally used to establish the connection. As with TDatabase, it is not critical that this component be used—each data component has the capability to form its own connection and can contain its own connection string.
ADO connects to a database via a Provider, which is a named OLE object that implements an OLE DB (Object Linking and Embedding Database) interface. The provider is contacted by the ADO facility when ADO is given a connection string. Some of the connection string is used by the ADO facility; the rest is passed on to the provider.
The Connection String
The connection string combines the features of a BDE alias and the more complex information that stands behind the alias. It can also be dentical to the ODBC connection string, in which case, the standard ODBC data provider will be used. That provider will access the specified installed ODBC driver to perform all operations.
Connection strings can be specific to the provider, but usually look something like the following (an example SQLServer connection string):
Provider=SQLOLEDB.1;Persist Security Info=False;User ID=sa;Initial Catalog=mydatabase
The connection string has the following components:
• Provider is the name by which the provider COM object can be found in the registry. In practice, you cannot necessarily know this name in advance. You should instead prompt the user for the provider. The only method of determining available providers is to either use the rather complex OLE DB enumerator technology in its raw form (that is, unsupported by components, see http://msdn.microsoft.com/library/default.asp?url=/library/en-us/oledb/htm/oledbroot_enumerator_object.asp) or to use the dialog box provided for constructing connection strings (discussed in a following section).
• User ID and Password can be supplied as is usually done in the Login Prompt property of BDE data components, except that under ODBC, the keywords are usually uppercase, whereas they are proper case in ADO.
• Initial Catalog is the name of the database desired.
The Home of Transactions
The TADOConnection is the place to start, commit, or roll back transactions. If you don’t specify a separate connection object, the documentation implies you can use the Connection property of the TADOTable or TADOQuery object to access an internal connection. This is just as you would use the Database property of a BDE data component to access the default database object of a BDE TSession.
Unfortunately, it does not work for ADO components because the Connection property remains NULL in an ADO object that has its own connection string, even once it is opened. Therefore, if you want transactions, you must create a separate TADOConnection object and use that as the connection for the TADOCustomDataSet descendant.