Previous Page TOC Next Page



- 13 -
Understanding MFC's DAO Classes


Until Microsoft created Visual C++ 4, database programmers had some difficulty justifying Visual C++ as a mainstream database development platform. Visual C++'s sole support for database developers was ODBC. Visual C++ didn't support the more powerful (and useful) Microsoft Jet database engine. In fact, Visual C++ programmers often were told by Visual Basic programmers that they had a better database development platform. Today, with Visual C++ 4, Visual C++ programmers are no longer at such a disadvantage. They now have access to the Microsoft Jet database engine and DAO (Database Access Objects).

WARNING

The DAO database classes are meant for single-threaded operation only. Don't try to utilize these classes in more than one thread at one time.

With Visual C++ 4, the DAO database classes are considered distinct from the MFC ODBC database classes. All of the DAO database class names have a prefix of CDao. Usually the DAO classes are more powerful than the ODBC classes. DAO classes use the Microsoft Jet database engine to access data. In turn, the Microsoft Jet database engine uses ODBC drivers to access data that isn't supported directly. The DAO classes also support the Data Definition Language (DDL) operations—for example, operations for creating databases and adding tables and fields via the classes—all without having to call DAO directly.

This chapter documents the new MFC classes that support the DAO interface. These classes (seven main new classes and several more supporting classes and structures) are very similar to their ODBC database counterparts, such as CDatabase and CRecordset.

Generally, the majority of Visual C++ database applications will be written using AppWizard and will be expanded by the programmer to become complete, working database applications. It's possible to write a database application from scratch using the DAO database classes—and a few programmers do. However, neither Microsoft nor the authors recommend doing this. With this in mind, your database application will have a few of the classes included by AppWizard (these classes are described next). During the development cycle, you will probably add other classes.

The MFC classes for DAO are like all other MFC classes. They serve as wrappers, encapsulating DAO's basic functionality. For example:

This process continues through the other DAO MFC classes.

Not all of the DAO functionality is encapsulated in the DAO MFC classes. You'll find that the major DAO objects are supported, but some objects, such as fields, indexes, parameters, and relations, aren't directly supported by the DAO MFC objects.



NOTE

There are three technical papers (called Technical Notes) specific to DAO:


TN053 Writing Custom DFX Routines for DAO Database Classes
TN054 Calling DAO Directly While Using MFC DAO Classes
TN055 Migrating MFC ODBC Database Class Applications to MFC DAO Classes



NOTE

Technical Note 54 (in the Visual C++ Books Online, see Visual C++ Books, MFC 4.0, MFC Technical Notes) has an example of using nonencapsulated DAO functionality in an MFC application.


Table 13.1 shows a mapping of DAO objects to MFC classes. The Comments and Related ODBC Classes column lists the corresponding ODBC class when applicable.

Table 13.1. The MFC-to-DAO object map.

MFC Class DAO Object Comments and Related ODBC Classes
CDaoWorkspace Workspace Manages the transaction space. Provides the Microsoft Jet database engine access.
CDaoDatabase Database Represents a connection to a specific database. Similar to CDatabase.
CDaoTableDef Tabledef Determines and manipulates the structure of a given table.
CDaoQueryDef Querydef Saves queries in a database.
CDaoRecordset Recordset Manages the result set, a set of records based on a table or selected by a query. Similar to CRecordset.
CDaoException Error MFC responds to all DAO errors by throwing exceptions of this type.
CDaoFieldExchange None Manages the exchange of data between a record in the database and the field data members of a recordset. Similar to CFieldExchange.

The DAO MFC Classes


The following sections document the DAO MFC classes by showing significant member functions and giving examples of usage.

As I mentioned earlier, some of the DAO MFC classes have ODBC analogues. This makes it easier to convert ODBC applications to use the DAO MFC classes. Generally, if you're unsure whether you should use DAO or ODBC, you should choose DAO to base your application on if the underlying database structure is either Access or one of the database structures that DAO supports directly (such as FoxPro).



NOTE

All DAO functions require the DAO header. Use the statement #include <afxdao.h>. When you use AppWizard to create an application, the #include is added automatically.




NOTE

See the DAO MFC documentation for more information about each of the DAO MFC classes. Simply search for the class name in the Books Online in Visual C++.



CDaoWorkspace


The CDaoWorkspace object is the highest object in the DAO hierarchy. It represents the DAO Workspace object. The DAO workspace defines the session for the user. It contains open databases and support for simultaneous transactions.

The CDaoWorkspace object manages named database sessions (from initial logon to logoff) for a single user. This database may be password protected. Generally, an application will use a single workspace. With AppWizard applications, it's unnecessary to create an explicit Workspace object. If your application needs multiple sessions, you can create additional Workspace objects. For each Workspace object, there may be more than one open database object at any given time. Under MFC's implementation, the workspace is basically a manager of transactions.

The CDaoWorkspace class provides the following functionality:

The DAO MFC classes don't implement the security control Users and Groups collections. When security is a concern, you will need to provide the necessary interface using direct calls to the underlying DAO interface.



NOTE

For information on accessing the underlying DAO interface, go to Books Online and search for the topic Technical Note 54.


The CDaoWorkspace call may be used to do the following things:

In order to use CDaoWorkspace to create a new workspace that doesn't exist in the Workspaces collection, use the CDaoWorkspace.Create() member function. With CDaoWorkspace, workspace objects won't persist between Microsoft Jet database engine sessions. If your application links MFC statically (that is, you link the MFC code using a static library rather than a DLL), when the application ends, the Microsoft Jet database engine will still be initialized. However, if the application uses MFC using the MFC DLL, the Microsoft Jet database engine will be uninitialized when the MFC DLL is unloaded.

Use the Open() member function to open an existing workspace. Use the Close() member function to close a workspace session. When Close() is called, all databases that haven't already been closed will be closed. Also, all uncommitted transactions will be rolled back (discarded).

DAO is used to manage transactions at the workspace level. As such, any transactions to workspaces with more than one open database will be applied to all open databases. For example, if there are two databases with uncommitted updates, and there is a call to CommitTrans(), all of the updates are committed, regardless of which database the changes are being applied to. When it's necessary to limit your transactions to one of a number of open databases, you must create a separate workspace object for the database to which you wish to limit your transactions.

Your application will use the DAO default workspace implicitly when the following events occur:

The CDaoWorkspace class provides a host of other database operations, such as repairing corrupted databases or compacting databases. Table 13.2 lists the members of the CDaoWorkspace class.

Table 13.2. The CDaoWorkspace class members.

Member Description
Data Members
m_pDAOWorkspace A pointer to the basic underlying DAO workspace object.
Construction
CDaoWorkspace() A constructor for the CDaoWorkspace object. After creating the CDaoWorkspace object, you must call either Create() or Open().
Attributes
GetIsolateODBCTrans() Returns a value used to indicate whether multiple transactions that involve the same ODBC data source are isolated.
GetName() Returns the user-defined name for the Workspace object.
GetUserName() Returns the user name (workspace owner) specified when the workspace was created.
IsOpen() Returns a nonzero value if the workspace is open.
SetIsolateODBCTrans() Specifies whether multiple transactions that involve the same ODBC data source will be isolated.
Operations
Append() Appends a newly created workspace to the database engine's Workspaces collection.
BeginTrans() Begins a new transaction. The new transaction will apply to all databases open in the workspace.
Close() Closes the workspace and all of the objects it contains. If there are any pending transactions, they are rolled back (discarded).
CommitTrans() Completes the current transaction and saves the specified changes.
CompactDatabase() Compacts (or duplicate) the database.
Create() Creates a new DAO Workspace object.
GetDatabaseCount() Returns a value that indicates the number of DAO Database objects in the workspace's Databases collection.
GetDatabaseInfo() Returns information about a specified DAO database defined in the workspace's Databases collection.
GetWorkspaceCount() Returns the number of DAO Workspace objects in the database engine's Workspaces collection.
GetWorkspaceInfo() Returns information about a specified DAO workspace defined in the database engine's Workspaces collection.
Open() Explicitly opens a workspace object associated with DAO's default workspace.
RepairDatabase() Attempts to repair a damaged database.
Rollback() Ends the current transaction. Any changes won't be saved.
Idle() Allows the database engine to perform background tasks.
Database Engine Properties
GetVersion() Returns a string that contains the version of the database engine associated with the workspace.
GetIniPath() Returns the location of the Microsoft Jet database engine's initialization settings in the Windows registry.
GetLoginTimeout() Returns the number of seconds before an error occurs when the user attempts to log in to an ODBC database.
SetDefaultPassword() Sets the password that the database engine uses when a workspace object is created without a specific password.
SetDefaultUser() Sets the user name that the database engine uses when a workspace object is created without a specific user name.
SetIniPath() Sets the location of the Microsoft Jet database engine's initialization settings in the Windows registry.

CDaoDatabase


The CDaoDatabase object is used to represent the connection to a database (from the CDaoWorkspace object) through which you can operate on the database's data.



NOTE

For more information on which database formats are supported, refer to the CDaoWorkspace::GetName() member function in the Visual C++ Books Online.


More than one CDaoDatabase object may be active at a given time in a given CDaoWorkspace object. The workspace maintains a collection of open database objects called the Databases collection. For more information, see the section "CDaoWorkspace."

You can create CDaoDatabase database objects implicitly when you create Recordset objects. You also can create a CDaoDatabase object explicitly. If you want to use an existing database explicitly with CDaoDatabase, you can do one of the following:



NOTE

It's possible to create a new Microsoft Access (.MDB) database. First, construct a CDaoDatabase object, and then call the CDaoDatabase object's Create() member function. It's not proper to call Open() after Create() in this situation.


When using CDaoDatabase, you may open an existing database by creating the CDaoDatabase object and then calling the Open() member function.

Each of these techniques will append a CDaoDatabase object to your CDaoWorkspace object and then open a connection to the database's data. You then will create CDaoRecordset, CDaoTableDef, or CDaoQueryDef objects to utilize the database. When CDaoRecordset, CDaoTableDef, or CDaoQueryDef objects are created, you pass to the constructors for these objects a pointer to your CDaoDatabase object. When the application has finished working with the connection, a call to the Close() member function closes the connection. You then must close any recordsets that you haven't already closed and destroy the CDaoDatabase object.



NOTE

If you already know ODBC, things might be starting to look familiar since ODBC and DAO share a common model. The following paragraphs discuss transaction processing—which, except for class names, works like ODBC's transaction processing.


DAO provides transaction processing at the workspace level. See the CDaoWorkspace::BeginTrans, CDaoWorkspace::CommitTrans, and CDaoWorkspace::Rollback functions in the Visual C++ Books Online. For additional information about transactions, search for the article "DAO Workspace: Managing Transactions" in the Programming with MFC title in Books Online.

As I mentioned earlier, DAO can interface with ODBC data sources. Microsoft recommends that you attach your ODBC data sources to a Microsoft Access (.MDB) database as external tables. For further information about this technique, see the article "DAO External: Working with External Data Sources" in the Programming with MFC title in Books Online.

With DAO, each database will maintain its own collections of Tabledef, Querydef, Recordset, and Relation objects. The DAO CDaoDatabase class will supply the necessary member functions to allow your application to manipulate these objects. These objects are stored in DAO itself, not in the DAO MFC class objects. There are also MFC classes for Tabledef, Querydef, and Recordset objects. There is no MFC class for Relation objects at this time.

Table 13.3 lists the members of the CDaoDatabase class.

Table 13.3. The CDaoDatabase class members.

Member Description
Data Members
m_pWorkspace A pointer to the CDaoWorkspace object that contains the database.
m_pDAODatabase A pointer to the underlying DAO CDaoDatabase object.
Construction
CDaoDatabase Constructs the CDaoDatabase object. After construction, you call Open() to connect the object to a database.
Attributes
CanTransact() Returns a nonzero value if the database supports transactions.
CanUpdate() Returns a nonzero value if the CDaoDatabase object may be updated. If the Database object is read-only, this function returns a zero value.
GetConnect() Returns the connect string that was used to connect the CDaoDatabase object to a database.
GetName() Returns the name of the database currently in use.
GetQueryTimeout() Returns the time-out period (in seconds) after which database query operations will time out.
GetRecordsAffected() Returns a count of the number of records that were affected by the last update, edit, add operation, or call to Execute().
GetVersion() Returns the version of the database engine associated with the database.
IsOpen() Returns a nonzero value if the CDaoDatabase object is currently connected to a database.
SetQueryTimeout() Sets in seconds the time-out period after which database query operations will fail. SetQueryTimeout() affects all subsequent open, add new, update, and delete operations.
Operations
Close() Closes the database connection.
Create() Creates the underlying DAO database object and then initializes the CDaoDatabase object.
CreateRelation() Defines a new relation among the tables in the database.
DeleteQueryDef() Deletes a Querydef object saved in the database's QueryDefs collection.
DeleteRelation() Deletes existing relations between tables in the database.
DeleteTableDef() Deletes a table's definition in a database. When that table's definition is deleted, all the table's data is also deleted.
Execute() Causes the action query to be executed. This query shouldn't return any results. If the executed query returns any results, an exception of type CDaoException is returned.
GetQueryDefCount() Returns the number of queries defined for the database.
GetQueryDefInfo() Returns information about a specified query defined in the database.
GetRelationCount() Returns the number of relations defined between tables in the database.
GetRelationInfo() Returns information about a specified relation defined between tables in the database.
GetTableDefCount() Returns the number of tables defined in the database.
GetTableDefInfo() Returns information about a specified table in the database.
Open() Opens a database and establishes a connection to it.

CDaoTableDef


The DAO CDaoTableDef object is used to represent the stored definition of a base table or a table that is attached. Each DAO database object has a collection called TableDefs that contains all the saved DAO Tabledef objects.

You can manipulate a table definition with CDaoTableDef. Here are some things you can do using CDaoTableDef:

To work with an existing table or create a new table, you will use Tabledef objects. First, construct a CDaoTableDef object. Next, give CDaoTableDef a pointer to a CDaoDatabase object to which the table belongs. Then you have to do one of the following things. What you do depends on what you want to do in your application:

It's easy to create tables using Microsoft Access. Open the database in Access, create your tables, and save the database. Using Access for this type manipulation is easier than trying to have your Visual C++ application perform these tasks. Of course, if your application must perform this functionality, and you're reasonably sure that all users of your application won't have Access available, you'll have to perform this task using your Visual C++ application instead of Access.

You specify a name for the Tabledef with a dbOpenTable value in the nOpenType parameter when opening a CDaoRecordset.

When using a Tabledef object to create a CDaoRecordset object, you might follow the steps just mentioned. After creating the object, construct your Recordset object using a pointer to your Tabledef object when you call CDaoRecordset::Open(). When you pass a Tabledef, it must be open.

As with other objects, when you're finished using the Tabledef object, call its Close() member function. After closing the Tabledef object, destroy it.

Table 13.4 lists the members of the CDaoTableDef class.

Table 13.4. The CDaoTableDef class members.

Member Description
Data Members
m_pDatabase Contains a pointer to the source database for this table.
m_pDAOTableDef Contains a pointer to the DAO interface underlying this Tabledef object.
Construction
Append() Adds a new table to the database.
CDaoTableDef() Constructs a CDaoTableDef object.
Close() Closes an open Tabledef.
Create() Creates a table that can be added to the database using the Append() function.
Open() Opens an existing Tabledef stored in the database's TableDefs collection.
Attributes
CanUpdate() Determines whether a table can be updated. If CanUpdate() returns a nonzero value, the table can be updated.
GetAttributes() Determines the characteristics of a CDaoTableDef object.
GetConnect() Gets information about the source of a table.
GetDateCreated() Gets the creation date and time for the base table underlying a CDaoTableDef object.
GetDateLastUpdated() Gets the date and time of the last change to the base table.
GetFieldCount() Determines the number of fields in the table.
GetFieldInfo() Obtains information about fields in the table.
GetIndexCount() Determines the number of indexes to the table.
GetIndexInfo() Obtains information about indexes to the table.
GetName() Obtains the user-defined table name.
GetRecordCount() Determines the number of records in the table.
GetSourceTableName() Obtains the name of the attached table in the source database.
GetValidationRule() Obtains the validation rule that is used to validate the data in a field as it is changed or added to a table.
GetValidationText() Obtains a value that specifies the text of the message that your application displays if the value of a Field object doesn't satisfy the specified validation rule.
IsOpen() Determines whether a table is open or not. Returns a zero value if the table isn't open.
SetAttributes() Sets the value that is used to change one or more characteristics of a CDaoTableDef object.
SetConnect() Sets values that are used in the connection to the table.
SetName() Sets the name of the table.
SetSourceTableName() Sets the source table's name.
SetValidationRule() Sets a validation rule. The validation rule is used every time data in a field is changed (or added) to a table.
SetValidationText() Sets the message that is to be displayed whenever data doesn't meet the specifications described by the validation rule.
Operations
CreateField() Creates a field for a table.
CreateIndex() Creates an index for a table.
DeleteField() Deletes a field from a table.
DeleteIndex() Deletes an index from a table.
RefreshLink() Updates the connection information for an attached table.

CDaoQueryDef


A Querydef is a query definition that is usually (but doesn't have to be) stored or saved in a database. Access databases often have query definitions stored in them. Querydefs consist of SQL statements that describe a query, the query's properties (such as the date it was created), and the time-out value. Since Querydefs don't need to be stored in a database, they can also be temporary objects. It isn't unusual for a Visual C++ front-end application to create a temporary Querydef object.



NOTE

Querydefs are always more efficient if they're stored in the database. Any Querydef that is to be executed frequently should always be saved in the database.


The CDaoDatabase object will maintain a collection, the QueryDefs collection, containing the object's saved Querydefs.

You can use CDaoQueryDef to work with saved queries and to create a new saved or temporary query. You would use CDaoQueryDef in the following way. First, you would create and construct your CDaoQueryDef object. This object would be supplied with the pointer to your CDaoDatabase object to which the query will belong. Next, you must do one of the following:

After you've finished using the Querydef object, call the Close() member function to close it. As soon as the Querydef is closed, destroy the CDaoQueryDef object.

You can easily create Querydef objects using Microsoft Access. Open the database, design your query, and save it. Your Visual C++ database application can then use the query.

A Querydef object is used for either of the following:

All types of queries can be used as Querydef objects. For example, queries can take the form of select, action, crosstab, delete, update, append, make-table, data definition, SQL pass-through, union, or bulk queries. The SQL statement that makes up the query determines the type of query.

See the Execute() and GetType() member functions in the Visual C++ Books Online for more information about queries. A query that would return a set of rows (as a recordset) is usually in the form of SELECT rows FROM table types of SQL statements.

When you use a Querydef to create a CDaoRecordset object, you create (or open) a Querydef. Then a CDaoRecordset object would be created and passed a pointer to your Querydef object. This pointer would be passed in the call to CDaoRecordset::Open(). The Querydef you pass must itself be open. If the Querydef isn't open, it can't be used to create a recordset.

You would use a Querydef object to gain access to the native SQL dialect for an external (non-Access) database. If you needed to create a Transact SQL query (Transact is the version of SQL used by Microsoft SQL Server), you would create the query and store it as a Querydef object.

Table 13.5 lists the members of the CDaoQueryDef class.

Table 13.5. The CDaoQueryDef class members.

Member Description
Data Members
m_pDatabase Contains a pointer to the CDaoDatabase object to which the Querydef is associated, whether the Querydef is saved or not.
m_pDAOQueryDef Contains a pointer to the OLE interface for the underlying DAO Querydef object.
Construction
CDaoQueryDef() Constructs the CDaoQueryDef object. After the CDaoQueryDef object is created, you must call either Open() or Create().
Create() Creates the underlying DAO Querydef object. The query can be either temporary or saved using a call to the Append() member function.
Append() Appends the Querydef to the database's QueryDefs collection. This will make the Querydef a saved (not temporary) object.
Open() Opens an existing Querydef stored in the database's QueryDefs collection.
Close() Closes the Querydef object.
Attributes
CanUpdate() Returns a zero result if the database can't be updated.
GetConnect() Obtains the connect string associated with the Querydef.
GetDateCreated() Obtains the query's creation date.
GetDateLastUpdated() Obtains the query's last update date.
GetName() Returns the name of the Querydef.
GetODBCTimeout() Obtains the ODBC timeout value.
GetRecordsAffected() Determines the count of how many records have been affected by an action query.
GetReturnsRecords() Returns zero if the query doesn't return any records.
GetSQL() Returns the SQL string that specifies the query defined by the Querydef.
GetType() Determines what the query type is. The query type could be delete, update, append, make-table, and so on.
IsOpen() Returns zero if the Querydef isn't open or can't be executed.
SetConnect() Sets the connect string for an SQL pass-through query on an ODBC data source.
SetName() Sets the name of the saved query. This new name replaces the name that was in use when the Querydef was created.
SetODBCTimeout() Sets the timeout period to be used by ODBC.
SetReturnsRecords() Specifies that the Querydef will return records.
SetSQL() Sets the SQL string that specifies the query defined by the Querydef.
Operations
Execute() Executes the query defined by the Querydef object.
GetFieldCount() Determines the number of fields that this Querydef has defined.
GetFieldInfo() Determines information about a field that is specified in the query.
GetParameterCount() Determines the number of parameters defined for the query.
GetParameterInfo() Obtains information about the specified parameter in the query.
GetParamValue() Gets the value of a specified parameter to the query.
SetParamValue() Sets the value of a specified parameter to the query.

CDaoRecordset


The DAO class CDaoRecordset is used to represent a set of records that have been selected from a datasource. CDaoRecordset corresponds directly to the CRecordset object that is used with ODBC.

The main difference between the DAO recordset and the ODBC recordset is that CDaoRecordset class objects access data through DAO, which is based on OLE, while the CRecordset classes access the database using ODBC.

A CDaoRecordset object is known as a recordset. A CDaoRecordset object can take one of three forms: a table-type recordset, a dynaset-type recordset, or a snapshot-type recordset:

The records contained in the recordset are fixed at the time the recordset is opened. Both the table-type recordset and dynaset-type recordset will reflect any changes made to data after the recordset was opened (by either the current process or perhaps by other users). In contrast, the snapshot recordset is static and isn't updated. Many applications use CDaoRecordset directly (usually using classes created using AppWizard). However, you can derive a class from CDaoRecordset if you wish. When you have a recordset object, you can do the following:

To use the CDaoRecordset object, first you must open a database and construct your CDaoRecordset object. A pointer to your CDaoDatabase object must be passed to the constructor. Alternatively, it's possible to create a CDaoRecordset object and have MFC create a temporary CDaoDatabase object.

After you've created the CDaoRecordset, you must call the Open() member function. It takes a parameter that specifies whether the object is to be a table-type recordset, a dynaset-type recordset, or a snapshot-type recordset. Calling Open() selects data from the database and retrieves the first record.

After you've created your recordset object, you then can use the object's member functions and data members to scroll through the records and perform operations on them.

The CDaoRecordset class uses DAO record field exchange (DFX) to support the reading and updating of record fields through type-safe C++ members of your CDaoRecordset or CDaoRecordset-derived class. See the CDaoFieldExchange object in the Visual C++ Books Online for more information.

Table 13.6 lists the members of the CDaoRecordset class.

Table 13.6. The CDaoRecordset class members.

Member Description
Data Members
m_bCheckCacheForDirtyFields Contains a flag indicating whether fields are automatically marked as changed or not.
m_pDAORecordset A pointer to the DAO interface underlying the recordset object.
m_nParams Has the number of parameter data members that will be found in the CDaoRecordset class.
m_pDatabase Contains a pointer to the source database that the result set was created from. The pointer is of type CDaoDatabase.
m_strFilter Contains a string that is used to construct an SQL WHERE statement.
m_strSort Contains a string used to construct an SQL ORDER BY statement.
Construction
CDaoRecordset() Constructs a CDaoRecordset object.
Close() Closes a CDaoRecordset object.
Open() Creates a new table, dynaset, or snapshot recordset.
Attributes
CanAppend() Determines if new records may be added to a recordset using the AddNew() member function. This function returns zero if new records can't be added to the recordset.
CanBookmark() If the recordset support bookmarks, this function returns a nonzero value.
CanRestart() If Requery() can be called to run the query again, this function returns a nonzero value.
CanScroll() If you can scroll through the records, this function returns a nonzero value.
CanTransact() If the datasource supports transactions, this function returns a nonzero value.
CanUpdate() If the datasource supports updates, this member function returns a nonzero value.
GetCurrentIndex() Used to obtain a CString that will contain the name of the index that was most recently used.
GetDateCreated() Obtains the date and time that the base table underlying the CDaoRecordset object was created.
GetDateLastUpdated() Obtains the date and time of the most recent change made to the design of a base table underlying a CDaoRecordset object.
GetEditMode() Returns a value that will indicate the editing state for the current record.
GetLastModifiedBookmark() Determines the most recently added or updated record.
GetName() Returns the name of the recordset as a CString.
GetParamValue() Retrieves the current value of the specified parameter stored in the underlying DAOParameter object.
GetRecordCount() Obtains the number of records accessed in a Recordset object.
GetSQL() Gets the SQL string used to select records for the recordset.
GetType() Determines the recordset's type: table, dynaset, or snapshot.
GetValidationRule() Retrieves the validation rule for a field.
GetValidationText() Retrieves the message text that is to be displayed when a validation rule isn't satisfied.
IsBOF() Returns a nonzero value if the recordset has been positioned before the first record. There is no current record.
IsDeleted() Returns a nonzero value if the recordset is currently positioned on a deleted record.
IsEOF() Returns a nonzero value if the recordset has been positioned after the last record. There is no current record.
IsFieldDirty() Returns a nonzero value if the specified field in the current record has been changed.
IsFieldNull() Returns a nonzero value if the specified field in the current record is null. Remember that null is different from NULL.
IsFieldNullable() Returns a nonzero value if the specified field in the current record can be set to null.
IsOpen() Returns a nonzero value if Open() has been called previously.
SetCurrentIndex() Sets an index on a table-type recordset.
SetParamValue() Sets the current value of the specified parameter stored in the underlying DAOParameter object.
SetParamValueNull() Sets the current value of the specified parameter to null.
Recordset Update Operations
AddNew() Sets up for adding new records. After the new records are prepared, a call to Update() will complete the record-adding process.
CancelUpdate() Called when it's necessary to abort or cancel pending updates due to an Edit() or an AddNew() operation.
Delete() Deletes the current record from the recordset. After the current record is deleted, it's necessary to explicitly scroll to another record.
Edit() Prepares for edits in the current record. After completing the edits, you must call Update() to update the record or call CancelUpdate() to cancel the changes.
Update() Completes an AddNew() or Edit() operation by saving the new or edited data on the data source.
Recordset Navigation Operations
Find() Finds the first, next, previous, or last location of a specified string in a recordset. The recordset must be a dynaset type that satisfies the specified criteria and makes that record the current record.
FindFirst() Finds the first location of a specified string in a recordset. The recordset must be a dynaset type that satisfies the specified criteria and makes that record the current record.
FindLast() Finds the last location of a specified string in a recordset. The recordset must be a dynaset type that satisfies the specified criteria and makes that record the current record.
FindNext() Finds the next location of a specified string in a recordset. The recordset must be a dynaset type that satisfies the specified criteria and makes that record the current record.
FindPrev() Finds the previous location of a specified string in a recordset. The recordset must be a dynaset type that satisfies the specified criteria and makes that record the current record.
GetAbsolutePosition() Returns the record number of a recordset object's current record.
GetBookmark() Returns a value that represents the bookmark on a record.
GetPercentPosition() Returns the position of the current record as a percentage of the total number of records.
Move() Repositions the recordset to a specified number of records relative to the current record. The move may be either forward or backward.
MoveFirst() Positions the current record to the first record in the recordset.
MoveLast() Positions the current record to the last record in the recordset.
MoveNext() Positions the current record to the next record in the recordset.
MovePrev() Positions the current record to the previous record in the recordset.
Seek() Finds a record and makes that record the current record.
SetAbsolutePosition() Sets the record number of a recordset object's current record.
SetBookmark() Positions the recordset to a record that contains the specified bookmark.
SetPercentPosition() Sets the position of the current record to a location that corresponds to a given percentage based on the total number of records in a recordset.
Other Recordset Operations
FillCache() Fills all (or a part) of the local cache for a recordset object.
GetCacheSize() Returns the number of records in a dynaset-type recordset to be locally cached.
GetCacheStart() Returns the bookmark value of the first record in the recordset to be cached.
GetFieldCount() Returns the number of fields in the recordset.
GetFieldInfo() Returns specific kinds of information about the fields in the recordset.
GetFieldValue() Returns a field's value.
GetIndexCount() Retrieves the number of indexes in a table.
GetIndexInfo() Returns information on an index.
GetLockingMode() Determines the type of locking that is in effect.
Requery() Reruns the recordset's query to refresh the selected records.
SetCacheSize() Sets the cache size.
SetCacheStart() Sets the bookmark of the first record in the recordset to be cached.
SetFieldDirty() Marks the specified field in the current record as changed.
SetFieldNull() Specifies that the field is null.
SetFieldValue() Specifies the value of a field in a recordset.
SetFieldValueNull() Sets the value of a field to null.
SetLockingMode() Sets the type of locking to put into effect during editing.
Overridables
DoFieldExchange() Performs the exchange of data between the field data members and the record set's current record.

CDaoException


The CDaoException object is used when handling exceptions when using the DAO MFC classes. The CDaoException class includes several public data members that may be used to analyze the error and assist you in determining the cause of the exception. CDaoException objects are constructed and thrown by member functions of the DAO database classes.

You can access exception objects within the scope of a CATCH expression. Your application also can throw a CDaoException object by using an AfxThrowDaoException() global function.



NOTE

The Microsoft documentation mentions the file DAOERR.H. This file is actually called DBDAOERR.H.


Table 13.7 lists error codes from DBDAOERR.H.

Table 13.7. DBDAOERR.H SCODE error code values.

Error Code Description
E_DAO_InternalError A reserved error, because there is no message for this error.
E_DAO_InvalidParameter Invalid argument.
E_DAO_CantBegin Couldn't start the session.
E_DAO_TransTooDeep Couldn't start the transaction. Too many transactions were already nested.
E_DAO_DatabaseNotFound Couldn't find the database.
E_DAO_DatabaseInvalidName Name specified isn't a valid database name.
E_DAO_DatabaseLocked Database is exclusively locked.
E_DAO_DatabaseOpenError Can't open the library database.
E_DAO_TableLocked Table is exclusively locked.
E_DAO_TableInUse Couldn't lock table because it's currently in use.
E_DAO_TableDuplicate Table already exists.
E_DAO_ObjectNotFound Couldn't find object.
E_DAO_ObjectDuplicate Object already exists.
E_DAO_CannotRename Couldn't rename installable ISAM file.
E_DAO_TooManyOpenTables Can't open any more tables.
E_DAO_IndexNotFound The index specified isn't an index in this table.
E_DAO_ColumnDoesNotFit Field won't fit in record.
E_DAO_ColumnTooBig The size of a field is too long.
E_DAO_ColumnNotFound Couldn't find the field.
E_DAO_NoCurrentIndex Operation invalid without a current index.
E_DAO_RecordNoCopy Update or CancelUpdate without AddNew() or Edit().
E_DAO_NoCurrentRecord No current record.
E_DAO_KeyDuplicate Duplicate value in index, primary key, or relationship. Changes were unsuccessful.
E_DAO_AlreadyPrepared AddNew() or Edit() already used.
E_DAO_FileNotFound Couldn't find file.
E_DAO_TooManyOpenFiles Can't open any more files.
E_DAO_DiskFull Not enough space on the disk.
E_DAO_PermissionDenied Can't update because the database or object is read-only.
E_DAO_CannotOpenSystemDb Can't start the application. The system database is missing or opened exclusively by another user.
E_DAO_InvalidLogon Not a valid account name or password.
E_DAO_InvalidAccountName Not a valid account name.
E_DAO_InvalidPassword Not a valid password.
E_DAO_InvalidOperation Can't perform this operation.
E_DAO_AccessDenied No permission for the operation has been granted.
E_DAO_NotInTransaction Commit or Rollback without BeginTrans.
E_DAO_OutOfMemory There is insufficient memory for the task.
E_DAO_CantAllocatePage Database has reached maximum size.
E_DAO_NoMoreCursors Can't open any more tables or queries.
E_DAO_OutOfBuffers There are not enough buffers for the task.
E_DAO_TooManyIndexes Couldn't create an index. Too many indexes are already defined.
E_DAO_ReadVerifyFailure Disk I/O error during read.
E_DAO_FilesysVersion Can't open a database created with a previous version of the application.
E_DAO_NoMoreFiles Out of MS-DOS file handles.
E_DAO_DiskError Disk or network error.
E_DAO_InvalidPath The path name specified isn't a valid path.
E_DAO_FileShareViolation Couldn't use the specified database; file already in use.
E_DAO_FileLockViolation Couldn't save the database; currently locked by another user.
E_DAO_RecordTooBig Record is too large.
E_DAO_TooManyOpenDatabases Can't open any more databases.
E_DAO_InvalidDatabase Can't open the database. Your application might not recognize it, or the file might be corrupt.
E_DAO_FileLockingUnavailable Couldn't lock file.
E_DAO_FileAccessDenied Couldn't open file.
E_DAO_SharingBufferExceeded MS-DOS file sharing lock count exceeded. You need to increase the number of locks installed with SHARE.EXE.
E_DAO_TaskLimitExceeded Too many client tasks.
E_DAO_TooManyLongColumns Too many Memo or OLE object fields.
E_DAO_InvalidFilename Not a valid filename.
E_DAO_AbortSalvage Couldn't repair this database.
E_DAO_LinkNotSupported Operation isn't supported on attached (linked) tables.
E_DAO_NullKeyDisallowed Index or primary key can't contain a null value.
E_DAO_OperationCanceled The user canceled the operation.
E_DAO_QueryParmTypeMismatch Wrong data type for the parameter.
E_DAO_QueryMissingParmsM Too few parameters. Expected |.
E_DAO_QueryDuplicateAliasM Duplicate output alias.
E_DAO_QueryDuplicateOutputM Duplicate output destination.
E_DAO_QueryIsBulkOp Can't open action query.
E_DAO_QueryIsNotBulkOp Can't execute a nonaction query.
E_DAO_QueryNoOutputsM Query or table must contain at least one output field.
E_DAO_QueryNoInputTablesM Query input must contain at least one table or query.
E_DAO_QueryInvalidAlias Not a valid alias name.
E_DAO_QueryInvalidBulkInputM The action query can't be used as a row source.
E_DAO_QueryUnboundRef Can't bind the name.
E_DAO_QueryExprEvaluation Can't evaluate the expression.
E_DAO_EvalEBESErr Error in the evaluation of the expression.
E_DAO_QueryNotUpdatable Operation must use an updatable query.
E_DAO_TableRepeatInFromList Can't repeat a table name in a FROM clause.
E_DAO_QueryExprSyntax Syntax error in the expression.
E_DAO_QbeExprSyntax Error in criteria expression.
E_DAO_FindExprSyntax Find expression has a syntax error in the expression.
E_DAO_InputTableNotFound Couldn't find the input table or query.
E_DAO_QueryAmbigRefM Ambiguous field reference.
E_DAO_JoinTableNotInput Joined table not listed in FROM clause.
E_DAO_UnaliasedSelfJoin Can't join more than one table with the same name.
E_DAO_ColumnNotInJoinTable JOIN operation refers to a nonjoined table.
E_DAO_QueryIsMGB Can't use an internal report query.
E_DAO_QueryInsIntoBulkMGB Can't insert data with an action query.
E_DAO_ExprUnknownFunctionM Undefined function in the expression.
E_DAO_QueryCannotDelete Couldn't delete from specified tables.
E_DAO_QueryTooManyGroupExprs Too many expressions in a GROUP BY clause.
E_DAO_QueryTooManyOrderExprs Too many expressions in an ORDER BY clause.
E_DAO_QueryTooManyDistExprs Too many expressions in a DISTINCT output.
E_DAO_Column2ndSysMaint Resultant table isn't allowed to have more than one Counter or Autonumber field.
E_DAO_HavingWOGrouping HAVING clause without grouping or aggregation.
E_DAO_HavingOnTransform Can't use the HAVING clause in a TRANSFORM statement.
E_DAO_OrderVsDistinct ORDER BY clause conflicts with DISTINCT.
E_DAO_OrderVsGroup ORDER BY clause conflicts with a GROUP BY clause.
E_DAO_AggregateInArgument Can't have an aggregate function in the expression.
E_DAO_AggregateInWhere Can't have an aggregate function in a WHERE clause.
E_DAO_AggregateInOrderBy Can't have an aggregate function in an ORDER BY clause.
E_DAO_AggregateInGroupBy Can't have an aggregate function in a GROUP BY clause.
E_DAO_AggregateInJoin Can't have an aggregate function in a JOIN operation.
E_DAO_NullInJoinKey Can't set a field in a join key to null.
E_DAO_ValueBreaksJoin There is no record in the table with key matching field(s).
E_DAO_QueryTreeCycle Circular reference caused by the parameter supplied.
E_DAO_OutputAliasCycle Circular reference caused by an alias in the query definition's SELECT list.
E_DAO_QryDuplicatedFixedSetM Can't specify a fixed column heading in a crosstab query more than once.
E_DAO_NoSelectIntoColumnName Missing a destination field name in a SELECT INTO statement.
E_DAO_NoUpdateColumnName Missing a destination field name in an UPDATE statement.
E_DAO_QueryNoInsertPerm Record(s) can't be added; no insert data permission is on.
E_DAO_QueryNoReplacePerm Record(s) can't be edited; no update data permission is on.
E_DAO_QueryNoDeletePerm Record(s) can't be deleted; no delete data permission is on.
E_DAO_QueryNoReadDefPerm Couldn't read definitions; there's no read design permission for the table or query.
E_DAO_QueryNoTblCrtPerm Couldn't create; there's no create permission for the table or query.
E_DAO_QueryNoReadPerm Record(s) can't be read; no read data permission is on.
E_DAO_QueryColNotUpd Can't update; the field isn't updatable.
E_DAO_QueryLVInDistinct Can't include a Memo or OLE object when you select unique values.
E_DAO_QueryLVInAggregate Can't have a Memo or OLE object in an aggregate argument.
E_DAO_QueryLVInHaving Can't have a Memo or OLE object in a criteria for an aggregate function.
E_DAO_QueryLVInOrderBy Can't sort on a Memo or OLE object.
E_DAO_QueryLVInJoin Can't join on a Memo or OLE object.
E_DAO_QueryLVInGroupBy Can't group on a Memo or OLE object.
E_DAO_DotStarWithGrouping Can't group on fields selected with *.
E_DAO_StarWithGrouping Can't group on fields selected with *.
E_DAO_IllegalDetailRef Argument isn't part of the aggregate function or grouping.
E_DAO_StarNotAtLevel0 Can't use * in a crosstab query.
E_DAO_QueryInvalidMGBInput Can't input from an internal report query.
E_DAO_InvalidName Name supplied isn't a valid name.
E_DAO_QueryBadBracketing Invalid bracketing of the name.
E_DAO_InsertIntoUnknownCol INSERT INTO statement contains an unknown field name.
E_DAO_QueryNoDeleteTables Must specify tables to delete from.
E_DAO_SQLSyntax Invalid SQL statement; expected DELETE, INSERT, PROCEDURE, SELECT, or UPDATE.
E_DAO_SQLDeleteSyntax Syntax error in a DELETE statement.
E_DAO_SQLFromSyntax Syntax error in a FROM clause.
E_DAO_SQLGroupBySyntax Syntax error in a GROUP BY clause.
E_DAO_SQLHavingSyntax Syntax error in a HAVING clause.
E_DAO_SQLInsertSyntax Syntax error in an INSERT statement.
E_DAO_SQLJoinSyntax Syntax error in a JOIN operation.
E_DAO_SQLLevelSyntax Syntax error in a LEVEL clause.
E_DAO_SQLMissingSemicolon Missing semicolon (;) at end of an SQL statement.
E_DAO_SQLOrderBySyntax Syntax error in an ORDER BY clause.
E_DAO_SQLParameterSyntax Syntax error in a PARAMETER clause.
E_DAO_SQLProcedureSyntax Syntax error in a PROCEDURE clause.
E_DAO_SQLSelectSyntax Syntax error in a SELECT statement.
E_DAO_SQLTooManyTokens Characters found after the end of an SQL statement.
E_DAO_SQLTransformSyntax Syntax error in a TRANSFORM statement.
E_DAO_SQLUpdateSyntax Syntax error in an UPDATE statement.
E_DAO_SQLWhereSyntax Syntax error in a WHERE clause.
E_DAO_RmtSQLCError ODBC: Call failed.
E_DAO_RmtDataOverflow Not documented by Microsoft.
E_DAO_RmtConnectFailed Not documented by Microsoft.
E_DAO_RmtIncorrectSqlcDll Not documented by Microsoft.
E_DAO_RmtMissingSqlcDll Not documented by Microsoft.
E_DAO_RmtConnectFailedM ODBC: Connection to the datasource failed.
E_DAO_RmtDrvrVer Not documented by Microsoft.
E_DAO_RmtSrvrVer Not documented by Microsoft.
E_DAO_RmtMissingOdbcDll ODBC: Couldn't find the DLL.
E_DAO_RmtInsertFailedM ODBC: Insert failed on an attached (linked) table.
E_DAO_RmtDeleteFailedM ODBC: Delete failed on an attached (linked) table.
E_DAO_RmtUpdateFailedM ODBC: Update failed on an attached (linked) table.
E_DAO_RecordLocked Couldn't save record; currently locked by another user.
E_DAO_InvalidBookmark Not a valid bookmark.
E_DAO_TableNotOpen Table isn't open.
E_DAO_DecryptFail Couldn't decrypt the file.
E_DAO_NullInvalid Null is invalid.
E_DAO_InvalidBufferSize Couldn't perform the operation; the data is too long for the field.
E_DAO_ColumnNotUpdatable Field can't be updated.
E_DAO_CantMakeINFFile Couldn't open the .INF file.
E_DAO_MissingMemoFile Missing memo file.
E_DAO_RecordDeleted Record is deleted.
E_DAO_INFFileError Invalid .INF file.
E_DAO_ExprIllegalType Illegal type in the expression.
E_DAO_InstalIsamNotFound Couldn't find the installable ISAM.
E_DAO_NoConfigParameters Couldn't find the net path or user name.
E_DAO_CantAccessPdoxNetDir Couldn't open PARADOX.NET.
E_DAO_NoMSysAccounts Couldn't open the table MSysAccounts in the system database file.
E_DAO_NoMSysGroups Couldn't open the table MSysGroups in the system database file.
E_DAO_DateOutOfRange Date is out of range or is in an invalid format.
E_DAO_ImexCantOpenFile Couldn't open the file.
E_DAO_ImexBadTableName Not a valid table name.
E_DAO_ImexOutOfMemory Not documented by Microsoft.
E_DAO_ImexEndofFile Encountered an unexpected end of file.
E_DAO_ImexCantWriteToFile Couldn't write to the file.
E_DAO_ImexBadRange Invalid range.
E_DAO_ImexBogusFile Invalid file format.
E_DAO_TempDiskFull Not enough space on the temporary disk.
E_DAO_RmtLinkNotFound Couldn't execute the query; couldn't find the attached (linked) table.
E_DAO_RmtTooManyColumns SELECT INTO remote database tried to produce too many fields.
E_DAO_ReadConflictM Couldn't save; currently locked by another user on a different machine.
E_DAO_CommitConflictM Couldn't read; currently locked by another user on a different machine.
E_DAO_SessionWriteConflict Couldn't update; currently locked by another session on this machine.
E_DAO_JetSpecialTableLocked Table is exclusively locked by another user.
E_DAO_TooManyColumns Too many fields are defined.
E_DAO_ColumnDuplicate Can't define a field more than once.
E_DAO_OutputTableNotFound Couldn't find the output table.
E_DAO_JetNoUserName The user name is unknown.
E_DAO_JetNoMachineName The machine name is unknown.
E_DAO_JetNoColumnName The column name is unknown.
E_DAO_DatabaseInUse Couldn't use the database; already in use.
E_DAO_DataHasChanged Data has changed; operation was stopped.
E_DAO_TooManySessions Couldn't start the session. Too many sessions are already active.
E_DAO_ReferenceNotFound Couldn't find the reference.
E_DAO_IntegrityViolMasterM Can't delete or change the record. Since related records exist in the table, referential integrity rules would be violated.
E_DAO_IntegrityViolSlaveM Can't add or change the record. Referential integrity rules require a related record in the table.
E_DAO_ReadConflict Couldn't save the database; currently locked by another user.
E_DAO_AggregatingHigherLevel Can't specify a subquery in the expression.
E_DAO_DatabaseDuplicate Database already exists.
E_DAO_QueryTooManyXvtColumn Too many crosstab column headers.
E_DAO_SelfReference Can't create a relationship between a field and itself.
E_DAO_CantUseUnkeyedTable Operation isn't supported on a Paradox table with no primary key.
E_DAO_IllegalDeletedOption Invalid deleted entry in the xBase section of the initialization setting.
E_DAO_IllegalStatsOption Invalid stats entry in the xBase section of the initialization setting.
E_DAO_ConnStrTooLong Connection string is too long.
E_DAO_TableInUseQM Couldn't lock the table; currently in use.
E_DAO_JetSpecialTableInUse Couldn't lock the specified table; currently in use by another user on a different machine.
E_DAO_IllegalDateOption Invalid date entry in the xBase section of the initialization setting.
E_DAO_IllegalMarkOption Invalid mark entry in the xBase section of the initialization setting.
E_DAO_BtrieveTooManyTasks Too many Btrieve tasks.
E_DAO_QueryParmNotTableid Parameter specified where a table name is required.
E_DAO_QueryParmNotDatabase Parameter specified where a database name is required.
E_DAO_WriteConflict Couldn't update; currently locked.
E_DAO_IllegalOperation Invalid operation.
E_DAO_WrongCollatingSequence Incorrect collating sequence.
E_DAO_BadConfigParameters Invalid entries in the Btrieve section of the initialization setting.
E_DAO_QueryContainsDbParm Query can't contain a database parameter.
E_DAO_QueryInvalidParmM The parameter isn't a valid parameter name.
E_DAO_BtrieveDDCorrupted Can't read the Btrieve data dictionary.
E_DAO_BtrieveDeadlock Encountered record locking deadlock while performing a Btrieve operation.
E_DAO_BtrieveFailure Errors encountered while using the Btrieve DLL.
E_DAO_IllegalCenturyOption Invalid century entry in the xBase section of the initialization setting.
E_DAO_IllegalCollatingSeq Invalid collating sequence.
E_DAO_NonModifiableKey Btrieve: Can't change field.
E_DAO_ObsoleteLockFile Out-of-date Paradox lock file.
E_DAO_RmtColDataTruncated ODBC: Field would be too long; data truncated.
E_DAO_RmtCreateTableFailed ODBC: Couldn't create the table.
E_DAO_RmtOdbcVer Not documented by Microsoft.
E_DAO_RmtQueryTimeout ODBC: Remote query time-out expired.
E_DAO_RmtTypeIncompat ODBC: Data type isn't supported on the server.
E_DAO_RmtUnexpectedNull Not documented by Microsoft.
E_DAO_RmtUnexpectedType Not documented by Microsoft.
E_DAO_RmtValueOutOfRange ODBC: Data is out of range.
E_DAO_TooManyActiveUsers Too many active users.
E_DAO_CantStartBtrieve Btrieve: Missing the Btrieve engine.
E_DAO_OutOfBVResources Btrieve: Out of resources.
E_DAO_QueryBadUpwardRefedM Invalid reference in the SELECT statement.