Record Field Exchange: Working with the Wizard Code
| Overview | How Do I | FAQ | Sample | | ODBC Driver List
This article explains the code that AppWizard and ClassWizard write to support RFX and how you might want to alter that code.
****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).
When you create a recordset class with ClassWizard (or with AppWizard), the wizard writes the following RFX-related elements for you, based on the data source, table, and column choices you make in the wizard:
Declarations of the recordset field data members in the recordset class.
An override of CRecordset::DoFieldExchange.
Initialization of recordset field data members in the recordset class constructor.
The Field Data Member Declarations
The wizards write a recordset class declaration in an .H file that resembles the following for class CSections
:
class CSections : public CRecordset
{
public:
CSections(CDatabase* pDatabase);
CSections::~CSections();
// Field/Param Data
//{{AFX_FIELD(CSections, CRecordset)
CString m_strCourseID;
CString m_strInstructorID;
CString m_strRoomNo;
CString m_strSchedule;
CString m_strSectionNo;
//}}AFX_FIELD
// Implementation
protected:
virtual CString GetDefaultConnect(); // Default connection string
virtual CString GetDefaultSQL(); // Default SQL for Recordset
virtual void DoFieldExchange(CFieldExchange* pFX); // RFX support
DECLARE_DYNAMIC(CSections)
};
Notice the following key features about the class above:
Special “//{{AFX_FIELD” comments that bracket the field data member declarations. ClassWizard uses these to update your source file.
The wizard overrides the DoFieldExchange member function of class CRecordset.
Caution Never edit the code inside “//{{AFX” brackets. Always use ClassWizard. If you add parameter data members or new field data members that you bind yourself, add them outside the brackets.
The DoFieldExchange Override
is the heart of RFX. The framework calls DoFieldExchange any time it needs to move data either from data source to recordset or from recordset to data source. DoFieldExchange also supports obtaining information about field data members through the and member functions.
The following DoFieldExchange override is for the CSections
class. ClassWizard writes the function in the .CPP file for your recordset class.
void CSections::DoFieldExchange(CFieldExchange* pFX)
{
//{{AFX_FIELD_MAP(CSections)
pFX->SetFieldType(CFieldExchange::outputColumn);
RFX_Text(pFX, "CourseID", m_strCourseID);
RFX_Text(pFX, "InstructorID", m_strInstructorID);
RFX_Text(pFX, "RoomNo", m_strRoomNo);
RFX_Text(pFX, "Schedule", m_strSchedule);
RFX_Text(pFX, "SectionNo", m_strSectionNo);
//}}AFX_FIELD_MAP
}
Notice the following key features of the function:
The special “//{{AFX_FIELD_MAP” comments. ClassWizard uses these to update your source file. This section of the function is called the “field map.”
A call to CFieldExchange::SetFieldType, through the pFX pointer. This call specifies that all RFX function calls up to the end of DoFieldExchange or the next call to SetFieldType are “output columns.” See for more information.
Several calls to the RFX_Text global function — one per field data member (all of which are CString variables in the example). These calls specify the relationship between a column name on the data source and a field data member. The RFX functions do the actual data transfer. The class library supplies RFX functions for all of the common data types. For more information about RFX functions, see the article Record Field Exchange: Using the RFX Functions.
****Note ****The order of the columns in your result set must match the order of the RFX function calls in
DoFieldExchange
.The pFX pointer to a object that the framework passes when it calls DoFieldExchange. The CFieldExchange object specifies the operation that DoFieldExchange is to perform, the direction of transfer, and other context information.
The Recordset Constructor
The recordset constructor that the wizards write contains two things related to RFX:
An initialization for each field data member.
An initialization for the data member, which contains the number of field data members.
The constructor for the CSections
recordset example looks like this:
CSections::CSections(CDatabase* pdb)
: CRecordset(pdb)
{
//{{AFX_FIELD_INIT(CSections)
m_strCourseID = "";
m_strInstructorID = "";
m_strRoomNo = "";
m_strSchedule = "";
m_strSectionNo = "";
m_nFields = 5;
//}}AFX_FIELD_INIT
}
****Important ****If you add any field data members manually, as you might if you bind new columns dynamically, you must increment m_nFields. Do so with another line of code outside the “//{{AFX_FIELD_INIT” brackets:
m_nFields += 3;
This is the code for adding three new fields. If you add any parameter data members, you must initialize the data member, which contains the number of parameter data members. Put the m_nParams initialization outside the brackets.