MFC - ODBC - 编程 - 图文 联系客服

发布时间 : 星期四 文章MFC - ODBC - 编程 - 图文更新完毕开始阅读684904d1284ac850ad0242fb

第6章 MFC ODBC编程 为了简化开发人员编写数据库应用程序,VC++的在其基础类库(MFC)里对ODBC API进行了封装,实现了一个面向对象的数据库编程接口,使VC++的数据库变得更加容易。 本章首先对MFC ODBC的概貌进行简要介绍,然后讲述利用MFC ODBC进行数据库开发的技巧,最后将通过具体数据库开发实例,详细讲述通过MFC ODBC开发数据库应用程序的方法和过程。 6.1 了解MFC ODBC MFC是Microsoft Foundation Class(微软基础类库)的缩写,它的设计目标是简化开发人员的工作。MFC使开发人员创建基于Windows的应用程序,而不必掌握下层的Windows体系结构。由于数据库应用程序是管理数据的重要方面,Microsoft开发了ODBC API的封装程序,为ODBC编程提供了一个面向对象的方法。 MFC对ODBC的封装主要是开发了CDatabase类和CRecordSet类。 6.1.1 CDatabase类 CDatabase类用于应用程序建立同数据源的连接。CDatabase类包含一个m_hdbc变量,它代表了数据源的连接句柄。如果要建立CDatabase类的实例,应先调用该类的构造函数,再调用Open函数,通过调用,初始化环境变量,并执行与数据源的连接。关闭数据源连接的函数是Close。 CDatabase类提供了对数据库进行操作的函数,为了执行事务操作,CDatabase类提供了BeginTrans函数,当全部数据都处理完成后,可以通过调用CommitTrans函数提交事务,或者在特殊情况下通过调用Rollback函数将处理回退。 CDatabase类提供的函数可以用于返回数据源的特定信息,例如通过GetConnect函数返回在使用函数Open连接数据源时的连接字符串,通过调用IsOpen函数返回当前的CDatabase实例是否已经连接到数据源上,通过调用CanUpdate函数返回当前的CDatabase实例是否是可更新的,通过调用CanTransact函数返回当前的CDatabase实例是否支持事务操作,等等。 总之,CDatabase类为C++数据库开发人员提供了ODBC的面向对象的编程接口。 6.1.2 CRecordSet类 要实现对结果集的数据操作,就要用到CRecordSet类。CRecordSet类定义了从数据库接收或者发送数据到数据库的成员变量,CRecordSet类定义的记录集可以是表的所有列,也可以是其中的一列,这是由SQL语句决定的。 CRecordSet类的成员变量m_hstmt代表了定义该记录集的SQL语句句柄,m_nFields第6章 MFC ODBC编程 成员变量保存了记录集中字段的个数,m_nParams成员变量保存了记录集所使用的参数个数。 CRecordSet的记录集通过CDatabase实例的指针实现同数据源的连接,即CRecordSet的成员变量m_pDatabase。 如果记录集使用了WHERE子句,m_strFilter成员变量将保存记录集的WHERE子句的内容,如果记录集使用了ORDER BY子句,m_strSort成员变量将保存记录集的ORDER BY子句的内容。 由多种方法可以打开记录集,最常用的方法是使用Open函数执行一个SQL SELECT语句。有如下四种类型的记录集: ? CRecordset::dynaset: 动态记录集,支持双向游标,并保持同所连接的数据源同步,对数据的更新操作可以通过一个fetch操作获取。 ? CRecordset::snapshot: 静态快照,一旦形成记录集,此后数据源的所有改变都不能体现在记录集里,应用程序必须重新进行查询,才能获取对数据的更新。该类型记录集也支持双向游标。 ? CRecordset::dynamic: 同CRecordset::dynaset记录集相比,CRecordset::dynamic记录还能在fetch操作里同步其它用户对数据的重新排序。 ? CRecordset::forwardOnly: 除了不支持逆向游标外,其它特征同CRecordset::snapshot相同。 6.2 MFC ODBC数据库访问技术 6.2.1 记录查询 使用CRecordSet的Open()和Requery()成员函数可以实现记录查询。需要注意的是,在使用CRecordSet的类对象之前,必须使用CRecordSet的成员函数Open()来获得有效的记录集。一旦使用过Open()函数,再次查询时使用Requery()函数就可以了。在调用Open()函数时,如果已经将一个打开的CDatabase对象指针传递给CRecordSet类对象的m_pDatabase成员变量,那么,CRecordSet类对象将使用该数据库对象建立ODBC连接;否则,如果m_pDatabase为空指针,对象就需要就新建一个CDatabase类对象并使其与缺省的数据源相连,然后进行CRecordSet类对象的初始化。缺省数据源由GetDefaultConnect()函数获得。也可以通过特定的SQL语句为CRecordSet类对象指定数据源,并以它来调用CRecordSet类的Open()函数,例如: myRS.Open(AFX_DATABASE_USE_DEFAULT,strSQL); 如果没有指定参数,程序则使用缺省的SQL语句,即对在GetDefaultSQL()函数中指定的SQL语句进行操作,代码如下: -113- 第6章 MFC ODBC编程 CString CMyRS::GetDefaultSQL() {return _T(\SELECT * FROM BasicData,MainSize 对于GetDefaultSQL()函数返回的表名,对应的缺省操作是SELECT语句,例如: 在查询过程中,也可以利用CRecordSet类的成员变量m_strFilter和m_strSort来执行条件查询和结果排序。m_strFilter用于指定过滤字符串,存放着SQL语句中关键字WHERE后的条件语句;m_strSort用于指定用于排序的字符串,存放着SQL语句中关键字ORDER BY后的字符串。例如: myRS.m_strFilter=\刘鹏'\myRS.m_strSort=\myRS.Requery(); SELECT * FROM BasicData,MainSize WHERE Name='刘鹏' ORDER BY Age 数据库查询中对应的SQL语句为: 除了直接赋值给成员变量m_strFilter以外,还可以通过参数化实现条件查询。利用参化可以更直观、更方便地完成条件查询任务。参数化方法的步骤如下: (1) 声明参变量,代码如下: CString strName; int nAge; (2) 在构造函数中初始化参变量如下: strName =_T(\nAge =0; m_nParams=2; pFX->SetFieldType(CFieldExchange::param) RFX_Text(pFX,_T(\RFX_Single(pFX,_T(\m_pmyRS->m_strFilter=\m_ pmyRS -> strName =\刘鹏\m_ pmyRS ->nAge=26; m_ pmyRS ->Requery(); (3) 将参变量与对应列绑定,代码如下: 完成以上步骤之后就可以利用参变量进行条件查询了,代码如下: 参变量的值按绑定的顺序替换查询字串中的“?”通配符。 如果查询的结果是多条记录,可以利用CRecordSet类的成员函数Move(),MoveNext(),MovePrev(),MoveFirst()和MoveLast()来移动记录光标。 6.2.2 记录添加 使用AddNew()成员函数能够实现记录添加,需要注意的是,在记录添加之前必须保证数据库是以允许添加的方式打开的,代码如下: m_ pmyRS ->AddNew(); // 在表的末尾添加新记录 m_ pmyRS ->SetFieldNull(&(m_pSet->m_type), FALSE); -114- 第6章 MFC ODBC编程 m_ pmyRS ->m_strName=\刘鹏\ m_ pmyRS -> // 输入新的字段值 m_ pmyRS ->m_nAge=26; // 输入新的字段值 Update(); // 将新记录存入数据库 // 重新建立记录集 m_ pmyRS ->Requery(); 6.2.3 记录删除 调用Delete()成员函数能够实现记录删除,在调用Delete()函数后不需调用Update()函数,代码如下: m_ pmyRS ->Delete(); if (!m_ pmyRS ->IsEOF()) else m_ pmyRS ->MoveLast(); m_ pmyRS ->MoveNext(); 6.2.4 记录修改 调用Edit()成员函数可以实现记录修改,在修改完成后需要调用Update()将修改结果存入数据库,代码如下: m_ pmyRS ->Edit(); ... // 将修改结果存入数据库 // 修改当前记录 m_ pmyRS ->m_strName=\刘波\修改当前记录字段值 m_ pmyRS ->Update(); m_ pmyRS ->Requery(); 6.2.5 撤销数据库更新操作 如果用户增加或者修改记录后希望放弃当前操作,可以在调用Update()函数之前调 用Move()函数,就可以使数据库更新撤销了,代码如下: CRecordSet::Move(AFX_MOVE_REFRESH); 该函数用于撤消增加或修改模式,并恢复在增加或修改模式之前的当前记录。其中参 数AFX_MOVE_REFRESH的值为零。 6.2.6 直接执行SQL语句 虽然通过CRecordSet类我们可以完成大多数的数据库查询操作,而且在CRecordSet类的Open()成员函数中也可以提供SQL语句,但有的时候我们还想进行一些其他操作, 例如建立新表、删除表、建立新的字段等等,这时就需要用到CDatabase 类的直接执行SQL语句的机制。通过调用CDatabase类的ExecuteSQL()成员函数就能够完成QL语句的直接执行,代码如下: BOOL CMyDB::ExecuteSQLWithReport (const CString& strSQL) { TRY { -115-