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.
E_DAO_ImexNoMatchingColumns None of the import field names match fields in the appended table.
E_DAO_ImexPasswordProtected Can't import a password-protected spreadsheet.
E_DAO_ImexUnparsableRecord Couldn't parse field names from the first row of the import table.
E_DAO_InTransaction Operation isn't supported in transactions.
E_DAO_RmtLinkOutOfSync ODBC: Linked table definition has changed.
E_DAO_IllegalNetworkOption Invalid NetworkAccess entry in the initialization setting.
E_DAO_IllegalTimeoutOption Invalid PageTimeout entry in the initialization setting.
E_DAO_CantBuildKey Couldn't build the key.
E_DAO_FeatureNotAvailable Operation isn't supported for this type of object.
E_DAO_IllegalReentrancy Can't open a form whose underlying query contains a user-defined function that attempts to set or get the form's RecordsetClone property.
E_DAO_UNUSED Not documented by Microsoft.
E_DAO_RmtDenyWriteIsInvalid ODBC: Can't lock all records.
E_DAO_ODBCParmsChanged Not documented by Microsoft.
E_DAO_INFIndexNotFound Index file isn't found.
E_DAO_SQLOwnerAccessSyntax Syntax error in the WITH OWNERACCESS OPTION declaration.
E_DAO_QueryAmbiguousJoins Query contains ambiguous outer joins.
E_DAO_InvalidColumnType Invalid field data type.
E_DAO_WriteConflictM Couldn't update; currently locked by another user on a different machine.
E_DAO_TableLockedM Not documented by Microsoft.
E_DAO_TableInUseMUQM Not documented by Microsoft.
E_DAO_InvalidTableId Invalid database object.
E_DAO_VtoNoFields No fields defined. Can't append Tabledef or Index.
E_DAO_VtoNameNotFound Item isn't found in this collection.
E_DAO_VtoFieldInCollection Can't append. The field is part of a TableDefs collection.
E_DAO_VtoNotARecordset Property can be set only when the field is part of a Recordset object's Fields collection.
E_DAO_VtoNoSetObjInDb Can't set this property once the object is part of a collection.
E_DAO_VtoIndexInCollection Can't append. The index is part of a TableDefs collection.
E_DAO_VtoPropNotFound Property isn't found.
E_DAO_VtoIllegalValue Invalid property value.
E_DAO_VtoNotArray Object isn't a collection.
E_DAO_VtoNoSuchMethod Method isn't applicable for this object.
E_DAO_NotExternalFormat External table isn't in the expected format.
E_DAO_UnexpectedEngineReturn Unexpected error from the external database driver.
E_DAO_InvalidDatabaseId Invalid database ID.
E_DAO_TooManyKeys Can't have more than 10 fields in an index.
E_DAO_NotInitialized Database engine hasn't been initialized.
E_DAO_AlreadyInitialized Database engine has already been initialized.
E_DAO_ColumnInUse Can't delete a field that is part of an index or is needed by the system.
E_DAO_IndexInUse Can't delete this index. It's either the current index or is used in a relationship.
E_DAO_TableNotEmpty Can't create the field or index in a table that is already defined.
E_DAO_IndexHasPrimary Primary key already exists.
E_DAO_IndexDuplicate Index already exists.
E_DAO_IndexInvalidDef Invalid index definition.
E_DAO_WrongMemoFileType Format of the memo file doesn't match the specified external database format.
E_DAO_ColumnCannotIndex Can't create an index on the given field.
E_DAO_IndexHasNoPrimary Paradox index isn't primary.
E_DAO_DDLConstraintSyntax Syntax error in a CONSTRAINT clause.
E_DAO_DDLCreateTableSyntax Syntax error in a CREATE TABLE statement.
E_DAO_DDLCreateIndexSyntax Syntax error in a CREATE INDEX statement.
E_DAO_DDLColumnDefSyntax Syntax error in field definition.
E_DAO_DDLAlterTableSyntax Syntax error in an ALTER TABLE statement.
E_DAO_DDLDropIndexSyntax Syntax error in a DROP INDEX statement.
E_DAO_DDLDropSyntax Syntax error in a DROP TABLE or DROP INDEX.
E_DAO_V11NotSupported Join expression isn't supported.
E_DAO_ImexNothingToImport Couldn't import the table or query. No records were found, or all records contain errors.
E_DAO_RmtTableAmbiguous There are several tables with this name. Specify owner in the format owner.table.
E_DAO_JetODBCConformanceError ODBC specification conformance error. This error should be reported to the ODBC driver vendor.
E_DAO_IllegalRelationship Can't create a relationship.
E_DAO_DBVerFeatureNotAvailable Can't perform this operation. Features in this version aren't available in databases with older formats.
E_DAO_RulesLoaded Can't change a rule while the rules for this table are in use.
E_DAO_ColumnInRelationship Can't delete this field. It's part of one or more relationships.
E_DAO_InvalidPin You must enter a personal identifier (PID) consisting of at least four and no more than 20 characters and digits.
E_DAO_RmtBogusConnStr Invalid connection string in pass-through query.
E_DAO_SingleColumnExpected At most, one field can be returned from a subquery that doesn't use the EXISTS keyword.
E_DAO_ColumnCountMismatch The number of columns in the two selected tables or queries of a union query don't match.
E_DAO_InvalidTopArgumentM Invalid TOP argument in a select query.
E_DAO_PropertyTooLarge Property setting can't be larger than 2K.
E_DAO_JPMInvalidForV1x This property isn't supported for external data sources or for databases created in a previous version.
E_DAO_PropertyExists Property specified already exists.
E_DAO_TLVNativeUserTablesOnly Validation rules and default values can't be placed on system or attached (linked) tables.
E_DAO_TLVInvalidColumn Can't place this validation expression on this field.
E_DAO_TLVNoNullM Field can't contain a null value.
E_DAO_TLVNoBlankM Field can't be a zero-length string.
E_DAO_TLVRuleViolationM Not documented by Microsoft.
E_DAO_TLVRuleVioNoMessage One or more values entered is prohibited by the validation rule set for the field.
E_DAO_QueryTopNotAllowedM Top not allowed in delete queries.
E_DAO_SQLUnionSyntax Syntax error in a union query.
E_DAO_TLVExprSyntaxM Syntax error in a table-level validation expression.
E_DAO_NoDbInConnStr No database is specified in the connection string or IN clause.
E_DAO_QueryBadValueListM Crosstab query contains one or more invalid fixed column headings.
E_DAO_QueryIsNotRowReturning Query can't be used as a row source.
E_DAO_QueryIsDDL Query is a DDL query and can't be used as a row source.
E_DAO_SPTReturnedNoRecords Pass-through query with ReturnsRecords property set to TRUE didn't return any records.
E_DAO_QueryIsSnapshot Recordset isn't updatable.
E_DAO_QueryExprOutput Field is based on an expression and can't be edited.
E_DAO_QueryTableRO Table is read-only.
E_DAO_QueryRowDeleted Record in table was deleted by another user.
E_DAO_QueryRowLocked Record in table is locked by another user.
E_DAO_QueryFixupChanged To make changes to this field, first save the record.
E_DAO_QueryCantFillIn Can't enter a value into a blank field on the "one" side of an outer join.
E_DAO_QueryWouldOrphan Records in the table would have no record on the "one" side.
E_DAO_V10Format Can be present only in version 1.0 format.
E_DAO_InvalidDelete DeleteOnly called with a nonzero cbData.
E_DAO_IllegalIndexDDFOption Btrieve: Invalid IndexDDF option in the initialization setting.
E_DAO_IllegalDataCodePage Invalid DataCodePage option in the initialization setting.
E_DAO_XtrieveEnvironmentError Btrieve: Xtrieve options aren't correct in the initialization setting.
E_DAO_IllegalIndexNumberOption Btrieve: Invalid IndexDeleteRenumber option in the initialization setting.
E_DAO_QueryIsCorruptM Query is corrupt.
E_DAO_IncorrectJoinKeyM Current field must match the join key on the "one" side of the outer join because it has been updated.
E_DAO_QueryLVInSubqueryM Invalid Memo or OLE object in the subquery.
E_DAO_InvalidDatabaseM Unrecognized database format.
E_DAO_TLVCouldNotBindRef Unknown or invalid reference in the validation expression or a default value in the table.
E_DAO_CouldNotBindRef Unknown or invalid field reference.
E_DAO_QueryWrongNumDestCol Number of query values and destination fields aren't the same.
E_DAO_QueryPKeyNotOutput Can't add record(s); the primary key for the table isn't in the recordset.
E_DAO_QueryJKeyNotOutput Can't add record(s); the join key of the table isn't in the recordset.
E_DAO_NumericFieldOverflow Numeric field overflow.
E_DAO_InvalidObject Object is invalid for the operation.
E_DAO_OrderVsUnion ORDER BY expression uses nonoutput fields.
E_DAO_NoInsertColumnNameM No destination field name in an INSERT INTO statement.
E_DAO_MissingDDFFile Btrieve: Can't find the file FIELD.DDF.
E_DAO_SingleRecordExpected At most, one record can be returned by this subquery.
E_DAO_DefaultExprSyntax Syntax error in default value.
E_DAO_ExclusiveDBConflict Database is opened by the user specified on the specified machine.
E_DAO_QueryIsNotDDL Query isn't a properly formed data-definition query.
E_DAO_SysDatabaseOpenError Can't open the Microsoft Jet engine system database.
E_DAO_SQLInvalidSPT Pass-through query must contain at least one character.
E_DAO_QueryTooComplex Query is too complex.
E_DAO_SetOpInvalidInSubquery Unions aren't allowed in a subquery.
E_DAO_RmtMultiRowUpdate Single-row update/delete affected more than one row of an attached (linked) table. The unique index contains duplicate values.
E_DAO_QueryNoJoinedRecord Record(s) can't be added; there's no corresponding record on the "one" side.
E_DAO_QueryLVInSetOp Can't use a Memo or OLE object field in a SELECT clause of a union query.
E_DAO_VtoInvalidOnRemote Property value isn't valid for REMOTE objects.
E_DAO_VtoNoFieldsRel Can't append a relation with no fields defined.
E_DAO_VtoObjectInCollection Can't append. The object is already in the collection.
E_DAO_DDLDiffNumRelCols Relationship must be on the same number of fields with the same data types.
E_DAO_DDLIndexColNotFound Can't find the field in the index definition.
E_DAO_DDLPermissionDenied Can't modify the table's design. It's in a read-only database.
E_DAO_DDLObjectNotFound Can't find the table or constraint.
E_DAO_DDLIndexNotFound No such index on the table.
E_DAO_DDLNoPkeyOnRefdTable Can't create the relationship. The referenced table doesn't have a primary key.
E_DAO_DDLColumnsNotUnique Specified fields aren't uniquely indexed in the table.
E_DAO_DDLIndexDuplicate Table already has an index with the same name.
E_DAO_DDLTableNotFound Table doesn't exist.
E_DAO_DDLRelNotFound No such relationship in the table.
E_DAO_DDLRelDuplicate There is already a relationship named in the current database.
E_DAO_DDLIntegrityViolation Can't create relationships to enforce referential integrity. Existing data in the table violates referential integrity rules with a related table.
E_DAO_DDLColumnDuplicate Field already exists in the table.
E_DAO_DDLColumnNotFound No field is named in the table.
E_DAO_DDLColumnTooBig The size of the field is too long.
E_DAO_DDLColumnInRel Can't delete the field. It's part of one or more relationships.
E_DAO_VtoCantDeleteBuiltIn Can't delete a built-in property.
E_DAO_VtoUDPsDontSupportNull User-defined properties don't support a Null value.
E_DAO_VtoMissingRequiredParm Property must be set before using this method.
E_DAO_JetJetInitInvalidPath Can't find the TEMP directory.
E_DAO_TLVExprUnknownFunctionM Unknown function in the validation expression or default value.
E_DAO_QueryNotSupported Query support unavailable.
E_DAO_AccountDuplicate Account name already exists.
E_DAO_JetwrnPropCouldNotSave An error has occurred. Properties weren't saved.
E_DAO_RelNoPrimaryIndexM There is no primary key in the table.
E_DAO_QueryKeyTooBig Can't perform a join, group, sort, or indexed restriction. A value being searched or sorted on is too long.
E_DAO_PropMustBeDDL Can't save the property because it's a schema property.
E_DAO_IllegalRIConstraint Invalid referential integrity constraint.
E_DAO_RIViolationMasterCM Can't perform a cascading operation. Since related records exist in the table, referential integrity rules would be violated.
E_DAO_RIViolationSlaveCM Can't perform a cascading operation. There must be a related record in the table.
E_DAO_RIKeyNullDisallowedCM Can't perform a cascading operation. It would result in a null key in the table.
E_DAO_RIKeyDuplicateCM Can't perform a cascading operation. It would result in a duplicate key in the table.
E_DAO_RIUpdateTwiceCM Can't perform a cascading operation. It would result in two updates on fields in the table.
E_DAO_RITLVNoNullCM Can't perform a cascading operation. It would cause a field to become null, which isn't allowed.
E_DAO_RITLVNoBlankCM Can't perform a cascading operation. It would cause a field to become a zero-length string, which isn't allowed.
E_DAO_RITLVRuleViolationCM Can't perform a cascading operation. Caused by the fact that there are related records in another table, and referential integrity rules would be violated.
E_DAO_RITLVRuleVioCNoMessage Can't perform a cascading operation. The value entered is prohibited by the validation rule set.
E_DAO_TLVRuleEvalEBESErr Error in the validation rule.
E_DAO_TLVDefaultEvalEBESErr Error in the default value.
E_DAO_BadMSysConf The server's MSysConf table exists, but it's in an incorrect format. Contact your system administrator.
E_DAO_TooManyFindSessions Too many FastFind sessions were invoked.
E_DAO_InvalidColumnM Invalid field name in the definition of the index or relationship.
E_DAO_REPReadOnly Not documented by Microsoft.
E_DAO_RIInvalidBufferSizeCM Invalid entry. Can't perform the cascading operation specified in the table because the value entered is too big for the field.
E_DAO_RIWriteConflictCM Not documented by Microsoft.
E_DAO_JetSpecialRIWriteConflictCM Can't perform a cascading update on the table because it's currently in use by another user on a different machine.
E_DAO_RISessWriteConflictCM Can't perform a cascading update on the table because it's currently in use.
E_DAO_NoBlank Zero-length string is valid only in a text or Memo field.
E_DAO_FutureError Not documented by Microsoft.
E_DAO_QueryInvalidBulkInput An action query can't be used as a row source.
E_DAO_NetCtrlMismatch Can't open the specified table. Another user has the table open using a different network control file or locking style.
E_DAO_4xTableWith3xLocking Can't open this Paradox 4.x or 5.x table because ParadoxNetStyle is set to 3.x in the initialization setting.
E_DAO_VtoObjectNotSet Object is invalid or not set.
E_DAO_VtoDataConvError Data type conversion error.

All the error codes that appear in Table 13.8 are from DBDAOERR.H. You can edit this file and create an intelligent error handler if you want by creating a large select/case selection block. Of course, you can elect not to handle the errors that aren't applicable to your application to keep your error handler's size within reason.

Table 13.8 lists the members of the CDaoException class.

Table 13.8. The CDaoException class members.

Member Description
Data Members
m_scode The SCODE value associated with the error. See Table 13.7 for a list of the valid SCODE values.
m_nAfxDaoError Contains the extended error code for errors that occur in the MFC DAO classes.
m_pErrorInfo Contains a pointer to the CDaoErrorInfo object that will contain information about one DAO error object.
Construction
CDaoException() Constructs the CDaoException object.
Operations
GetErrorCount() Returns a count of how many errors are in the Microsoft Jet database engine's errors collection.
GetErrorInfo() Returns error information about a particular error object, specified by the nIndex parameter, from the errors collection.

CDaoFieldExchange


The CDaoFieldExchange class is used to transfer data from fields in a result set to the CDaoRecordset member variables. You need to use this class only if you're going to write data exchange routines for custom data types. If you're only using standard data types, you won't need to use the CDaoFieldExchange object. This process, called DFX, manages the exchange in both directions from the result set and to the result set.



NOTE

Technical Note 53 (in Visual C++ Books Online, see Visual C++ Books, MFC 4.0, MFC Technical Notes) has an example of how to write DFX routines.


Like other features of DAO, the design and usage of the DAO record field exchange (DFX) is based on the same model as ODBC's record field exchange (RFX). If you're comfortable with ODBC's RFX, you'll find it easy to use DAO's DFX.

The CDaoFieldExchange object is used to provide the context information that DAO needs for the record field exchange. The CDaoFieldExchange object supports a number of operations, including binding parameters and field data members and setting various flags (null, dirty, and so on) on fields in the current record. The DFX operations are performed on CDaoRecordset data members defined by the enum FieldType in CDaoFieldExchange. Possible FieldType values are

You use the IsValidOperation() member when you're going to write your own (custom) DFX functions. You do this by using the SetFieldType() member function, which is often done in your CDaoRecordset::DoFieldExchange functions.

Table 13.9 lists the members of the CDaoFieldExchange class.

Table 13.9. The CDaoFieldExchange class members.

Member Description
Data Members
m_nOperation Holds the current DFX operation being performed.
m_prs Holds a pointer to the current CDaoRecordset on which the DFX operation is being performed.
Member Functions
IsValidOperation() Returns a zero if the current operation isn't appropriate for the type of field being updated.
SetFieldType() Sets the type of CDaoRecordset data member that is to be represented until the next call to SetFieldType().

CDaoRecordView


The CDaoRecordView class is used to display database records using a dialog box template. This class, derived from CFormView (which is in turn derived from CScrollView, and so on), is virtually identical to ODBC's CRecordView.

The view presented by CDaoRecordView is connected directly to a CDaoRecordset object. As with CRecordView, you create a dialog box (usually with AppWizard) and locate appropriate dialog controls to display fields from the datasource. The CDaoRecordView object uses standard dialog data exchange (DDX) and DAO record field exchange (DFX) to actually move the record's data to and from the CDaoRecordView dialog box's controls. CDaoRecordView will also supply the default implementation for record navigation so that you can easily implement moves to the first, next, previous, or last record in the data source. CDaoRecordView also provides the interface for updating the record currently in view.

Most programmers (at least the nonmasochistic ones) will use AppWizard to create the shell for their DAO database application. If you don't use AppWizard, you'll find it rather difficult to create MFC Windows applications. The most common way to create your record view is with AppWizard. AppWizard creates both the record view class and its associated recordset class as part of your skeleton starter application.

You can use ClassWizard to add a CDaoRecordView later in the development process if necessary. However, before starting your application, you should decide what the application's user interface will look like.

When you use AppWizard to create your application's shell, you will be provided with toolbar buttons that the user will be able to use for record navigation. These AppWizard-supplied buttons let the user make the next, previous, first, or last record the current record.

The CDaoRecordView class maintains the current record's position in the recordset. The buttons for record navigation are enabled and disabled to prevent the user from making incorrect choices, such as attempting to select the previous record when the first record in the recordset is the current record.

Table 13.10 lists the members of the CDaoRecordView class.

Table 13.10. The CDaoRecordView class members.

Member Description
Construction
CDaoRecordView Constructs the CDaoRecordView object.
Attributes
OnGetRecordset() Provides a pointer to an object derived from CDaoRecordset. When you're using ClassWizard, this function is automatically overridden, and a CDaoRecordset object is created automatically for you if necessary.
IsOnLastRecord() Returns zero if the current record isn't the last record in the associated recordset.
IsOnFirstRecord() Returns zero if the current record isn't the first record in the associated recordset.
Operations
OnMove() Moves to the specified record, first updating the current record with any changes that have been made. The specified record may be next, previous, first, or last.

Summary


DAO is new to Visual C++ programmers. Although Visual Basic has offered DAO support for some time, Visual C++ programmers have had to work with ODBC, which doesn't offer the same capabilities as DAO. Visual Basic programmers have had a substantial advantage when working with Access database files.

DAO is managed using a set of MFC classes. These classes are similar to the MFC ODBC classes, but there are some differences. The MFC DAO classes can either directly or indirectly access all of the functionality of the Microsoft DAO/Access Jet Database Engine. The MFC DAO database classes presented in this chapter include

CDaoWorkspace

Each class was discussed, and the members of each class were described. This chapter also listed the errors that CDaoException handles.

Previous Page Page Top TOC Next Page