Home | Overview | How Do I | FAQ | Sample | Tutorial | ODBC Driver List
This article explains the RFX process. This is an advanced topic covering:
Note This article applies to classes derived from CRecordset in which bulk row fetching has not been implemented. If you are using bulk row fetching, then bulk record field exchange (Bulk RFX) is implemented. Bulk RFX is similar to RFX. To understand the differences, see the article Recordset: Fetching Records in Bulk (ODBC).
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, RFX binds (associates) each selected column to the address of the appropriate field data member. When the recordset updates a record, RFX calls ODBC API functions to send an SQL UPDATE or INSERT statement to the driver. RFX uses its knowledge of the field data members to specify the columns to write.
The framework backs up the edit buffer at certain stages so it can restore its contents if necessary. RFX 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. The edit buffer is not restored if you abandon a newly changed edit buffer by, for example, moving to another record before calling Update.
Besides exchanging data between the data source and the recordset’s field data members, RFX manages binding parameters. When the recordset is opened, any parameter data members are bound in the order of the “?” placeholders in the SQL statement that CRecordset::Open constructs. For more information, see the article Recordset: Parameterizing a Recordset (ODBC).
Your recordset class’s override of DoFieldExchange does all the work, moving data in both directions. Like dialog data exchange (DDX), RFX 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 RFX events as a recordset object is opened and as you add, update, and delete records. The table Using RFX: You and the Framework in the article Record Field Exchange: Using RFX shows the process at a high level, illustrating operations as a recordset is opened. The table Sequence of RFX Operations During Recordset Open and the table Sequence of RFX Operations During Scrolling in this article show the process as RFX processes a Move command in the recordset and as RFX manages an update. During these processes, DoFieldExchange is called to perform many different operations. The m_nOperation data member of the CFieldExchange object determines which operation is requested. You might find it helpful to read the articles Recordset: How Recordsets Select Records (ODBC) and Recordset: How Recordsets Update Records (ODBC) before you read this material.
The following RFX activities occur, in the order shown, when you call a recordset object’s Open member function:
The following table shows the sequence of RFX operations when you open a recordset.
Sequence of RFX Operations During Recordset Open
Your operation | DoFieldExchange operation | Database/SQL operation |
1. Open recordset. | ||
2. Build an SQL statement. | ||
3. Send the SQL. | ||
4. Bind parameter data member(s). | ||
5. Bind field data member(s) to column(s). | ||
6. ODBC does the move and fills in the data. | ||
7. Fix up the data for C++. |
Recordsets use ODBC’s “prepared execution” to allow for fast requerying with the same SQL statement. For more information about prepared execution, see the ODBC SDK Programmer’s Reference on the MSDN Library CD.
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 RFX operations when the user moves from record to record.
Sequence of RFX Operations During Scrolling
Your operation | DoFieldExchange operation | Database/SQL operation |
1. Call MoveNext or one of the other Move functions. | ||
2. ODBC 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 RFX perspective, the sequence is as follows:
Since a new record has no previous values to compare new ones with, AddNew sets the value of each field data member to a PSEUDO_NULL value. Later, when you call Update, RFX compares each data member’s value with the PSEUDO_NULL value. If there is 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 of these the same as C++ NULL.)
Unlike the Update call for AddNew, the Update call for Edit compares updated values with previously stored values rather than using PSEUDO_NULL. The difference is that AddNew has no previously stored values for comparison.
The following table shows the sequence of RFX operations when you add a new record or edit an existing record.
Sequence of RFX Operations During AddNew and Edit
Your operation | DoFieldExchange operation | Database/SQL operation |
1. Call AddNew or Edit. | ||
2. Back up the edit buffer. | ||
3. For AddNew, mark field data members as “clean” and Null. | ||
4. Assign values to recordset field data members. | ||
5. Call Update. | ||
6. Check for changed fields. | ||
7. Build SQL INSERT statement for AddNew or UPDATE statement for Edit. | ||
8. Send the SQL. | ||
9. For AddNew, restore the edit buffer to its backed-up contents. For Edit, delete the backup. |
When you delete a record, RFX 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 RFX sequence information.
See Also ClassWizard: Creating a Recordset Class, Macros and Globals, CFieldExchange, CRecordset::DoFieldExchange