MFC ODBC 编程
来源:百度文库 编辑:神马文学网 时间:2024/04/29 22:53:29
MFC ODBC 编程
1 了解 MFC ODBC
MFC 对 ODBC 的封装主要是开发了CDatabase 类和 CRecordSet 类。
CDatabase类主要是为了建立应用程序和数据源的连接功能。
CRecordSet类主要是对数据集的操作。
记录的查询:主要使用CRecordSet类的Open()方法和Requery()成员函数。在使用CRecordSet的类对象之前,必须使用CRecordSet的成员函数Open()来获得有效的记录集。一旦使用过Open()函数,再次查询时使用Requery()函数就可以了。
记录的添加:只用AddNew()函数,不过必须保证在数据库是在允许添加的模式打开的。
记录的删除:调用Delete()函数完成,在使用完Delete()函数之后不用调用Update()函数了。
记录的修改:调用Edit()函数完成,在使用过Edit()函数之后需要调用Update()函数将修改结果存入数据库。
撤销数据库更新操作:如果在增加、删除或者编辑记录之后,想撤销原来的操作,应该在Update()函数之前使用Move()函数。CRecordSet::Move(AFX_MOVE_REFRESH); 该函数用于撤消增加或修改模式,并恢复在增加或修改模式之前的当前记录。其中参 数AFX_MOVE_REFRESH的值为零。
直接执行SQL操作:这个需要调用CDatabase类的ExecuteSQL()函数。需要注意的是,由于不同DBMS提供的数据操作语句不尽相同,直接执行SQL语句可能会破坏软件的DBMS无关性,因此在应用中应当慎用此类操作。
MFC ODBC的数据库操作过程:
首先,应用程序应该先使用CDatabase类的Open()函数实现与ODBC数据源的连接,然后传递CDatabase类的指针到CRecordSet类的构造函数中,使CRecordSet对象与原来的数据源结合起来。完成了数据源的连接之后,大量的操作集中在数据集之上。完成操作之后,先关闭所有记录集的连接,然后关闭数据源的连接。
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 的面向对象的编程接口。
1.2 CRecordSet 类
CRecordSet 类实现对结果集的数据操作。CRecordSet 类定义了从数据库接收或者发送数据到数据库的成员变量,CRecordSet 类定义的记录集可以是表的所有列,也可以是其中的一列,这是由 SQL语句决定的。
CRecordSet 类的成员变量m_hstmt 代表了定义该记录集的SQL 语句句柄,m_nFields成员变量保存了记录集中字段的个数,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 数据库访问技术
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 语句进行操作,代码如下:
CString CMyRS::GetDefaultSQL()
{return_T("[Name],[Age]");}
对于 GetDefaultSQL()函数返回的表名,对应的缺省操作是SELECT 语句,例如:
SELECT * FROM BasicData,MainSize
在查询过程中,也可以利用CRecordSet 类的成员变量m_strFilter 和 m_strSort 来执行条件查询和结果排序。m_strFilter 用于指定过滤字符串,存放着SQL 语句中关键字WHERE 后的条件语句;m_strSort 用于指定用于排序的字符串,存放着SQL 语句中关键字ORDER BY 后的字符串。例如:
myRS.m_strFilter="Name='刘鹏'";
myRS.m_strSort="Age";
myRS.Requery();
数据库查询中对应的SQL 语句为:
SELECT * FROM BasicData WHERE Name='刘鹏' ORDER BY Age
除了直接赋值给成员变量m_strFilter 以外, 还可以通过参数化实现条件查询。 利用参化可以更直观、更方便地完成条件查询任务。参数化方法的步骤如下:
(1) 声明参变量,代码如下:
CString strName;
int nAge;
(2) 在构造函数中初始化参变量如下:
strName =_T("");
nAge =0;
m_nParams=2;
(3) 将参变量与对应列绑定,代码如下:
pFX->SetFieldType(CFieldExchange::param)
RFX_Text(pFX,_T("Name"), strName);
RFX_Single(pFX,_T("Age"), nAge);
完成以上步骤之后就可以利用参变量进行条件查询了,代码如下:
m_pmyRS->m_strFilter="Name=? AND age=?";
m_ pmyRS -> strName ="刘鹏";
m_ pmyRS ->nAge=26;
m_ pmyRS ->Requery();
参变量的值按绑定的顺序替换查询字串中的“?”通配符。
如果查询的结果是多条记录,可以利用CRecordSet 类的成员函数Move(),MoveNext(),MovePrev(),MoveFirst()和MoveLast()来移动记录光标。
2.2 记录添加
使用 AddNew()成员函数能够实现记录添加,需要注意的是,在记录添加之前必须保证数据库是以允许添加的方式打开的,需要调用Update()更新,代码如下:
m_ pmyRS ->AddNew(); // 在表的末尾添加新记录
m_ pmyRS ->SetFieldNull(&(m_pSet->m_type),FALSE);
m_pmyRS->m_strName=”刘鹏”; //输入新的字段值
m_ pmyRS ->m_nAge=26; // 输入新的字段值
m_ pmyRS ->Update(); // 将新记录存入数据库
m_ pmyRS ->Requery(); // 重新建立记录集
2.3 记录删除
调用 Delete()成员函数能够实现记录删除,在调用Delete()函数后不需调用Update()函数,代码如下:
m_pmyRS ->Delete();
if(!m_ pmyRS ->IsEOF())
m_ pmyRS ->MoveNext();
else
m_ pmyRS ->MoveLast();
2.4 记录修改
调用 Edit()成员函数可以实现记录修改, 在修改完成后需要调用Update()将修改结果存入数据库, 代码如下:
m_ pmyRS ->Edit();
m_ pmyRS ->m_strName="刘波"; // 修改当前记录字段值
...
m_ pmyRS ->Update();
m_pmyRS->Requerey();
2.5 撤销数据库更新操作
如果用户增加或者修改记录后希望放弃当前操作,可以在调用Update()函数之前调 用 Move()函数,就可以使数据库更新撤销了,代码如下:
CRecordSet::Move(AFX_MOVE_REFRESH);
该函数用于撤消增加或修改模式,并恢复在增加或修改模式之前的当前记录。其中AFX_MOVE_REFRESH的值为零。
2.6 直接执行 SQL 语句
虽然通过 CRecordSet 类我们可以完成大多数的数据库查询操作,而且在CRecordSet 类的 Open()成员函数中也可以提供SQL 语句,但有的时候我们还想进行一些其他操作,例如建立新表、删除表、建立新的字段等等,这时就需要用到CDatabase 类的直接执行SQL 语句的机制。 通过调用CDatabase 类的 ExecuteSQL()成员函数就能够完成SQL 语句的直接执行,代码如下:
BOOL CMyDB::ExecuteSQLWithReport (const CString& strSQL)
{
TRY
{
m_pMyDB->ExecuteSQL(strSQL); // 直接执行 SQL 语句
}
CATCH(CDBException,e)
{
CString strMsg;
strMsg.LoadString(IDS_EXECUTE_SQL_FAILED);
strMsg+=strSQL;
return FALSE;
}
END_CATCH
return TRUE;
}
需要注意的是,由于不同DBMS 提供的数据操作语句不尽相同,直接执行SQL 语句可能会破坏软件的DBMS 无关性,因此在应用中应当慎用此类操作。
2.7 MFC ODBC 的数据库操作过程
ODBC API编程类似,MFC的ODBC编程也要先建立同ODBC 数据源的连接,这个过程由一个CDatabase对象的Open函数实现。然后CDatabase对象的指针将被传递到CRecordSet对象的构造函数里,使CRecordSet 对象与当前建立起来的数据源连接结合起来。
完成数据源连接之后, 大量的数据库编程操作将集中在记录集的CRecordSet 类操作上。在应用程序退出运行状态的时候, 需要将所有的记录集关闭,并关闭所有同数据源的连接。
3 本 章 小 结
本章介绍了 MFC ODBC 编程方法和过程。与ODBC API 编程相比,MFC 编程更适用于界面型数据库应用程序的开发,由于MFC 的广泛支持,ODBC 编程可以对数据进行很好地表示。
然而MFC 的 CDatabase 类和 CRecordset类提供的数据库操作函数非常有限,支持的游标类型也很有限,限制了高效的数据库开发。