Home | Overview | How Do I | FAQ | Sample | Tutorial | ODBC Driver List
This article explains the DFX process. This is a fairly advanced topic, covering:
Note This article is about the DAO version of record field exchange. If you are using the MFC ODBC classes rather than the MFC DAO classes, see the article Record Field Exchange: How RFX Works instead.
The recordset object’s field data members, taken together, constitute an edit buffer that holds the selected columns of one record. When the recordset is first opened and is about to read the first record, DFX binds (associates) each selected column to the address of the appropriate field data member. When the recordset updates a record, DFX calls DAO to send the appropriate commands to the database engine. DFX uses its knowledge of the field data members to specify the columns (fields) in the data source to write.
There are two ways of working with the edit buffer in a recordset:
By default, your recordsets keep a second copy of the edit buffer for most data types (excluding the variable-length types, such as text and binary data). The copy is used for comparison with the edit buffer, to detect changes. You can choose to turn double buffering off, but keeping it turned on simplifies managing record field updates, adding and deleting records, and so on. For more information about double buffering, see the article DAO Record Field Exchange: Double Buffering Records.
If you turn off the default double buffering, each time you edit a field you must call SetFieldDirty and SetFieldNull (passing the parameter FALSE). That is, you must take explicit actions so MFC does not have to compare the edit buffer with a copy to detect your changes. For more information, see the article DAO Record Field Exchange: Double Buffering Records.
If you have double buffering enabled (the default), the framework backs up the edit buffer at certain stages so it can restore its contents if necessary. With double buffering enabled, DFX backs up the edit buffer before adding a new record and before editing an existing record. It restores the edit buffer in some cases — for example, after an Update call following AddNew.
Besides exchanging data between the data source and the recordset’s field data members, DFX manages binding parameters. When the recordset is opened, any parameter data members are bound in the order of the named parameters in the SQL statement that CDaoRecordset::Open receives or constructs. For more information, see the article DAO Queries: Filtering and Parameterizing Queries.
Your recordset class’s override of DoFieldExchange does all the work, moving data in both directions. Like dialog data exchange (DDX), DFX needs information about the data members of your class. ClassWizard provides the necessary information by writing a recordset-specific implementation of DoFieldExchange for you, based on the field data member names and data types you specify with the wizard.
This section describes the sequence of DFX events as a recordset object is opened and as you scroll and add, update, and delete records. The table Using DFX: You and the Framework in the article DAO Record Field Exchange: Using DFX shows the process at a high level, illustrating operations as a recordset is opened. The table Sequence of DFX Operations During Recordset Open and the table Sequence of DFX Operations During Scrolling in this article show the process as DFX processes a Move command in the recordset and as DFX manages an update. During these processes, DoFieldExchange is called to perform many different operations. The m_nOperation data member of the CDaoFieldExchange object determines which operation is requested.
The following DFX activities occur, in the order shown, when you call a recordset object’s Open member function:
The following table shows the sequence of DFX operations when you open a recordset.
Sequence of DFX Operations During Recordset Open
Your operation | DoFieldExchange operation | Database operation |
1. Open the recordset. | ||
2. Build an SQL statement. DoFieldExchange might have a querydef, a tabledef, or an SQL statement handed to it. If not, MFC builds the statement. | ||
3. Open the querydef or tabledef, or create a temporary querydef (using either an SQL statement passed in or one built by MFC) and open it. | ||
4. Bind parameter data member(s). | ||
5. Bind field data member(s) to column(s). | ||
6. Create the recordset. | ||
7. DAO moves to the first record and fills in the data. | ||
8. Fix up the data for C++. |
When you scroll from one record to another, the framework calls DoFieldExchange to replace the values previously stored in the field data members with values for the new record.
The following table shows the sequence of DFX operations when the user moves from record to record.
Sequence of DFX Operations During Scrolling
Your operation | DoFieldExchange operation | Database operation |
1. Call MoveNext or one of the other Move functions. | ||
2. DAO does the move and fills in the data. | ||
3. Fix up the data for C++. |
If you add a new record, the recordset operates as an edit buffer to build up the contents of the new record. As with adding records, editing records involves changing the values of the recordset’s field data members. From the DFX perspective, the sequence is as follows:
Since a new record has no previous values to compare new ones with, AddNew (with double buffering) sets the value of each field data member to a PSEUDO_NULL value as described under CDaoFieldExchange::m_nOperation. Later, when you call Update, DFX compares each data member’s value with the PSEUDO_NULL value; if there’s a difference, the data member has been set. (PSEUDO_NULL is not the same thing as a record column with a true Null value; nor is either the same as C++ NULL.)
Note MFC does not use a PSEUDO_NULL value for COleDateTime or COleCurrency fields. Those data types have Nulls built in.
Unlike the Update call for AddNew, the Update call for Edit compares updated values with previously stored values rather than using PSEUDO_NULL, if double buffering is on. If double buffering is off, you must call SetFieldDirty after an edit (and SetFieldNull if appropriate). The difference between Edit and AddNew is that AddNew has no previous stored values for comparison.
The following table shows the sequence of DFX operations when you add a new record or edit an existing record.
Sequence of DFX Operations During AddNew and Edit
Your operation | DoFieldExchange operation | Database operation |
1. Call AddNew or Edit. | ||
2. Back up the edit buffer if double buffering is on. | ||
3. For AddNew, mark field data members as “clean” and Null. For Edit, call Edit in DAO. | ||
4. Assign values to recordset field data members. | ||
5. Call Update. | ||
6. Check for changed fields if double buffering is on. | ||
7. Propagate changes to the database. Call Update in DAO. | ||
8. For AddNew, restore the edit buffer to its backed-up contents if double buffering is on. If it is off, the values set for the new record remain in the recordset data members. For Edit, delete the backup if double buffering is on. | ||
9. If double buffering is off, you must refresh the current record after AddNew. Call Move with the AFX_MOVE_REFRESH parameter to restore the record that was previously current. |
When you delete a record, DFX sets all the fields to NULL as a reminder that the record is deleted and you must move off it. You won’t need any other DFX sequence information.
In the Class Library Reference see CDaoFieldExchange, CDaoRecordset::DoFieldExchange, and, under Macros and Globals, Record Field Exchange Functions.
See Also DAO: Where Is..., DAO Record Field Exchange (DFX), DAO Record Field Exchange: Using DFX, DAO Record Field Exchange: Working with the Wizard Code, DAO Record Field Exchange: Using the DFX Functions, ClassWizard