Home | Overview | How Do I | FAQ | Sample | Tutorial | 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:
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:
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.
DoFieldExchange 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 IsFieldDirty and IsFieldNull 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:
Note The order of the columns in your result set must match the order of the RFX function calls in DoFieldExchange
.
The recordset constructor that the wizards write contains two things related to RFX:
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 m_nParams data member, which contains the number of parameter data members. Put the m_nParams initialization outside the brackets.