荔园在线
荔园之美,在春之萌芽,在夏之绽放,在秋之收获,在冬之沉淀
[回到开始]
[上一篇][下一篇]
发信人: Peter (小飞侠), 信区: Program
标 题: VC4.0下ODBC参数化 记录集与动态绑定方法的实现编程?
发信站: BBS 荔园晨风站 (Wed Jan 27 17:43:06 1999), 转信
运用参数化记录集与动态绑定技术是ODBC应用程序中提高程序运行
效率的常用方法。与用C语言直接调用ODBC函数的做法相比,VC4.0及
其所包含的MFC基本类库提供了方便地实现上述方法的手段。下面将
具体介绍VC4.0中参数化记录集与动态绑定方法的实现。
参数化记录集与动态绑定
在利用ODBC开发Client/Server应用程序的过程中,程序员必然会
遇到这样的问题:如何快速高效执行查询操作,既要充分利用Client/S
erver结构的优点,又要尽量少占用数据库服务器的资源。在VC4.0中
常用的方法是先根据表的结构利用Class Wizard生成一个对应表的CR
ecordSet的派生类,然后根据不同的查询条件修改筛选字符串类的数
据成员m_strField的值,并调用Requery()成员函数以得到满足指定条
件的记录集。但是,通过分析程序的执行过程及MFC的源代码可知:在
每次建立一个新的筛选字符串后,CRecordSet类根据所对应的表的结
构生成一个SQL语句,并经ODBC驱动程序提交给服务器执行。服务器在
接到请求以后首先要对此SQL语句进行语法分析以及优化,将SQL语句
所定义的操作分解,然后提交给服务器数据库引擎执行,并将最终结果
返回给客户。这样当筛选字符串具有相同的形式而仅仅只有筛选参数
取值不同时,每次进行这样相同的操作将严重浪费服务器的资源。
针对上述情况ODBC接口提供了参数化记录集的功能,即可以生成
一个满足通过一些参数给定查询条件的记录集,直接修改这些参数就
可以得到满足不同条件的记录集。这样由于参数化记录集中参数直接
传递给数据库引擎,避免了每次对相同的SQL语句进行上述操作,因而
大大提高了SQL语句的执行效率,特别是针对重复的、结构相似的查询
,这种提高更显著。而动态绑定技术则允许应用程序根据不同的条件
绑定不同的数据项,这样可以在程序中利用一个CRecordSet的实例分
别存储多个表中的数据或者操作用户在程序运行中生成的新表(因为
利用Class Wizard生成CRecordSet的派生类时,必须先有确定的表的
结构)。这对于减少程序占用机器资源以及提高程序的灵活性具有重
要意义。
参数化记录集的实现
下面以一个学生学籍表为例,通过生成一个将学生学号作为参数
的记录集来说明VC4.0中参数化记录集的实现。该表的结构如下:
表1
操作步骤如下:
1.利用VC4.0中的Class Wizard工具创建对应于Student Table的
CRecordSet类的派生类CStudentSet。
2.在CStudentSet的头文件中为该类加入一个公有的CString类的
数据成员m_strStuden t_Param,注意此数据成员必须加在一对AFX_FI
ELD注释之外。
//在一对AFX_FIELD注释之中定义的变量即被绑定列对应的变量
。
//{{AFX-FIELD(CStudentSet,CRecordSet)
CString m_Student_Name;
CString m_Student_NO;
CString m_Home_Address;
CString m_Telephone_NO;
CString m_Home_Zip;
//}}AFX_FIELD
//被绑定参数列对应的变量
CString m_strStudent_Param;
3.把新的成员变量加到DoField Exchange方法中,参数正是通过
该方法传递到驱动程序中去的。在把参数增加到DoFieldExchange方
法之前,必须先调用SetFieldType函数表明后面的字段是参数值。
void CStudentSet::DoFieldExchange(CFieldExchange * pFX)
{
//{{AFX_FIELD_MAP(CStudentSet)
pFX->SetFieldType(CFieldExchange::outputColumn);
//说明绑定列
RFX->Text(pFX,_T("[Student_Name]"),m_Student_Name);
RFX->Text(pFX,_T("Student_NO"),m_Student_NO);
RFX->Text(pFX,_T("[Home_Address〗"),m_Home_Address);
RFX->Text(pFX,_T("[Telephone_NO〗"),m_Telephone_NO);
RFX->Text(pFX,_T("[Home_Zip〗"),m_Home_Zip);
//}}AFX_FIELD_MAP
pFX->SetFieldType(CFieldExchange::param);
//说明绑定参数
RFX->Text(pFX,_T("Studnet-NO"),m_strStudent_Param);
}
4.建立参数化筛选字符串,在构造函数中将CStudentSet中从CRec
ordSet继承的数据成员m_strField初始化成包含未知参数的形式;同
时初始化参数和m_nParam。
CStudentSet::CStudentSet(CDatabase * pDb):CRecordSet(m_p
Db)
{
//参数初始化
//{{AFX_FIELD_INIT(CWhiteboardSet)
m_Student_Name=_T("");
m_Student_NO=_T("");
m_Home_Address=_T("");
m_Telephone_NO=_T("");
m_Home_Zip=_T("");
m_nFields=5;//绑定列数目
//}}AFX_FIELD_INIT
m_strStudent_Param=_T("");
m_nParams=1;//参数数目
m_strFilter="Student-NO=?";
}
其中"?"即代表参数所在的位置,在包含多个参数的情鱿?ODBC
引擎将按DoFieldExcha nge方法中参数出现的顺序替换m_strField中
的问号。m_nParam的值必须与参数的实际个数相等,否则将引起一些
难以觉察的错误。
这样,每次根据学生学号来查找学生信息时,只须简单地为m_strS
tudent_Param赋值,并调用Requery()则可得到给定学号的学生信息。
动态绑定的实现
我们仍以Student Table为例,假设我们现在根据用户的选择只须
要绑定Student_NO列和其它三列中的某一列或某几列。
首先,我们在CStudentSet中加入一个CStringList成员变量和一
个CObList成员变量,其中CStringList用于存放字段名,CObList用于
存放与CStringList字段名对应的变量的指针。
其次,修改DoFieldExchange方法。
注意在调用Requery()以前必须修改m_nField的值:
m_nField=m_Column_List.GetCount();
这样,通过往m_Column_List和m_Storage_List中成对地填入字段
名和对应的变量名,即可实现动态绑定。
具有动态绑定特性的CStudentSet类的详细结构及实现如下:
// studentSet.h CStudentSet类头文件
class CStudentSet:public CRecordset
{
public:
CStudentSet(CDatabase* pDatabase=NULL);
DECLARE_DYNAMIC(CStudentSet)
//设置绑定参数
//{{AFX_FIELD(CStudentSet,CRecordset)
CString m_Student_Name;
CString m_Student_NO;
CString m_Home_Address;
CString m_Telephone_NO;
CString m_Home_Zip;
//}}AFX_FIELD
//添加存储动态绑定对象的链表
public:
CStringList m_Column_List;
CObList m_Storage_List;
//{{AFX_VIRTUAL(CStudentSet)
public:
virtual CString GetDefultConnect();
// Default connection string
virtual CString GetDefaultSQL();
//default SQL for Recordset
virtual void DoFieldExchange(CFieldExchange* pFX);
//RFX support
//}}AFX_VIRTUAL
#ifdef _DEBUG
virtual void AssertValid() const;
virtual void Dump(CDumpContext & dc) const;
#endif
};
// studentSet.cpp CStudentSet 类CPP文件
#include "stdafx.h"
#include "student.h"
#include "studentSet.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE〖〗=--FILE--_;
#endif
IMPLEMENT_DYNAMIC(CStudentSet,CRecordset)
CStudentSet::CStudentSet(CDatabase* pdb): CRecordset(pdb
)
{ //参数初始化
//{{AFX_FIELD_INIT(CStudentSet)
m_Student_Name=_T("");
m_Student_NO=_T("");
m_Home_Address=_T("");
m_Telephone_NO=_T("");
m_Home_Zip=_T("");
m_nFields=5;
//}}AFX_FIELD_INIT
m_nDefaultType=snapshot;
}
CString CStudentSet::GetDefaultConnect()
{
return _T("ODBC;DSN=Student");
}
CString CStudentSet::GetDefaultSQL()
{
return _T("Student");
}
//修改后的DoFieldExchange方法函数
void CStudentSet::DoFieldExchange(CFieldExchange* pFX)
{
//{{AFX_FIELD_MAP(CStudentSet)
pFX->SetFieldType(CFieldExchange::outputColumn);
POSITION pos=m_Column_List.GetHeadPosition();
while(pos!=NULL)
RFX_Text(pFx,m_Column_List.GetNext(pos),
*m_Storage_List.GetNext(pos));
//}}AFX_FIELD_MAP
}
//CStudentSet diagnostics
#ifdef _DEBUG
void CStudentSet::AssertValid() const
{
CRecordset::AssertValid();
}
void CStudentSet::Dump(CDumpContext& dc) const
{
CRecordset::Dump(dc);
}
#endif //_DEBUG
--
※ 来源:.BBS 荔园晨风站 bbs.szu.edu.cn.[FROM: 192.168.1.3]
[回到开始]
[上一篇][下一篇]
荔园在线首页 友情链接:深圳大学 深大招生 荔园晨风BBS S-Term软件 网络书店