2、RFX功能代码
在MFC里提供了一系列RFX 调用函数,这些RFX函数负责在数据源的数据表列与记录集对象的字段数据之间交换数据,这种交换是可以双向进行的。一般是通过使用ClassWizard在记录集类的DoFieldExchange成员函数中自动编写RFX函数调用的,这类函数有一个指向CFieldExchange类对象的指针,只需简单的传递指向CFieldExchange的 pFX指针给DoFieldExchange即可。DoFieldExchange函数被频繁的提及,其实该函数可以说是RFX的中枢,任何时候程序框架需要在数据源和记录集之间进行任何数据交换都必须通过该函数的中介才能完成,其作用同用来进行对话框数据交换的DoDataExchange()有些类似。该函数的典型代码如下:
void CMyDB::DoFieldExchange(CFieldExchange* pFX)
{
//{{AFX_FIELD_MAP(CSections)
pFX->SetFieldType(CFieldExchange::outputColumn);
RFX_Text(pFX,"序号",m_strID);
……
//}}AFX_FIELD_MAP
}
其中"//{{AFX_FIELD_MAP"中的代码被成为字段映射,通过RFX函数来处理各个字段。DoFieldExchange()函数执行时,通过pFX指针调用CFieldExchange类成员函数SetFieldType(),这指定了直到DoFieldExchange函数末尾或下一次SetFieldType调用范围内的所有RFX函数都是用于字段处理(ouput columns)的。在DoFieldExchange中为每一个字段数据成员都根据数据类型的不同而调用相应的RFX函数,这些调用指定了数据源的列与字段数据成员之间的对应关系,同时,它们之间的数据交换任务也是由这些RFX函数完成的。根据数据类型的不同,提供有不同的RFX函数:
| RFX函数 | 数据交换类型 |
| RFX_Binary | 转换CbyteArray型的字节数组数据 |
| RFX_Bool | 转换布尔型数据 |
| RFX_Byte | 转换单字节数据 |
| RFX_Date | 使用CTime或TIMESTAMP_STRUCT转换时间或日期 |
| RFX_Double | 转换双精度数据 |
| RFX_Int | 转换整型数据 |
| RFX_Long | 转换长整型数据 |
| RFX_LongBinary | 使用CLongBinary对象转换大型二进制数据 |
| RFX_Text | 转换字符串数据 |
| RFX_Single | 转换单精度数据 |
至于为RFX提供支持的CFieldExchange类,在一般情况下是不需要程序开发人员进行直接干预的,但在编写自定义的数据交换模块时可以手工编写调用该类的代码。该类在功能上提供了记录数据交换或多行数据交换所需要的上下文环境,而且还支持诸如绑定参数和字段数据成员等操作。
Bulk RFX机制分析
MFC ODBC数据库类提供了对多行存取的支持,这种从数据源一次取回多个记录的Bulk RFX(批量记录字段交换)机制在大数据量的情况下效率是比较高的。但需要特别注意的Bulk RFX只能实现从数据源到记录集对象的单向数据流动。在用Open函数打开记录集对象之前,可以用SetRowSize()来定义行集的大小,缺省状态是25条。在使用Bulk RFX的Open函数时必须将dwOptions参数指定为CRecordset::useMultiRowFetch。虽然使用多行存取可以在某种程度上提高程序的性能,但在具体使用时必须要考虑到以下几个细节,否则将会导致失败或不可预料的错误:
首先,程序提供的DoBulkFieldExchange成员函数只提供从数据源到记录集对象的单向数据传输,因此用户不能使用诸如AddNew()、Edit()和Update()等试图写往数据源的函数。
其次,不能使用IsDeleted、SetFieldDirty等成员函数,但在编程中可以采取一些变通的方法,比如可以用GetRowStatus来代替IsDeleted。
最后需要特别注意的是,对记录集的指针的移动必须以行集为单位,这是比较容易理解的。总的来说Bulk RFX机制同RFX是非常相似的,使用的Bulk RFX函数也基本上是在原RFX函数的基础上扩充具备了多行存取的功能。
小结
本文主要对MFC ODBC数据库编程中数据源和数据集对象间数据交换这一环节展开讨论,并重点在概念和使用上对这一环节的RFX和用于多行存取的Bulk RFX机制进行了介绍。通过本文使程序开发人员能够对RFX和Bulk RFX的数据交换机制有一个比较好的认识。
