CODBCAccess: CDatabase 和 CRecordset 的包装器





5.00/5 (9投票s)
2001年12月4日
12分钟阅读

218890

4306
一个对象,
引言
不久前,我正在做一个项目,需要使用数据库作为主要数据源。当时我对数据库不太熟悉,于是我决定写一个类来帮助使用数据源和MFC类CDatabase
和CRecordset
,从而更多地了解它们。我最终得到的是一个简单但有用的CDatabase
和CRecordset
的包装器,它将这两个类合并成一个类,能够管理CDatabase
对象和记录集。目前,该类主要面向Microsoft Access数据源驱动程序。将来,也许我会考虑使该类更通用地面向数据源驱动程序。
类概述
CODBCAccess
通过MFC类CDatabase
管理到数据源的ODBC连接。连接到数据源后,您可以对该数据库执行SQL命令并管理事务。此外,您还可以管理多达10个记录集,每个记录集都可以使用唯一的SQL语句打开。有了这个简短的介绍,下面进入类本身!
使用该类
在使用该类之前,必须将ODBCAccess.cpp和ODBCAccess.h添加到您的项目文件中。此外,由于该类使用了George Polouse编写的3个辅助类,您还需要将RecordsetEx.*、Columns.*和Tables.*添加到您的项目文件中。
CODBCAccess
的用法与其他类相同:声明一个对象并对其调用函数。您应该在stdafx.h
文件中包含以下代码行以添加数据库支持(仅当该行尚未在该文件中时):
#include <afxdb.h>
包含该文件后,请确保在要声明对象的文件中#include "ODBCAccess.h"
。要开始使用函数,请在堆栈上创建对象:CODBCAccess myDB;
CODBCAccess的构造函数仅设置一些内部变量,因此您现在需要连接到数据源。您可以使用CODBCAccess::Connect
函数连接到数据源,如下所示:
myDB.Connect("MyDatasource");
连接到数据源后,您可以执行多项操作:(1)使用函数CODBCAccess::SendSQL
发送SQL语句;(2)使用函数CODBCAccess::StartTransaction
和CODBCAccess::EndTransaction
启动或结束事务;(3)打开和管理记录集。由于事务函数非常直观(它们遵循CDatabase
等效函数的_基本思想_),我将尝试解释记录集操作。
该类管理多达10个记录集,每个记录集都是CRecordsetEx
类型的对象。每个记录集都有一个标识符名称,通常称为“友好名称”。当您要创建新记录集时,请调用函数CODBCAccess::OpenNewSet
,该函数将友好名称作为第一个参数,要执行的SQL语句作为第二个参数,以及您希望结果集包含的表名作为第三个参数。您必须指定SQL语句或表名,而不是两者都指定。示例调用如下:
//With an SQL statement: myDB.OpenNewSet("MyNewSet", "SELECT [Main].[ID] FROM [Main]"); //OR with a table name (this code would execute the SQL statement:函数
// SELECT * FROM [Main]) myDB.OpenNewSet("MyNewSet", "", "Main");
CODBCAccess::OpenNewSet
会检查传入的友好名称,如果已存在同名记录集,则返回false。如果友好名称未使用过,它将创建一个新的CRecordsetEx
并使用传入的信息将其打开。一旦您有了打开的记录集,就可以通过调用函数CODBCAccess::GetSet
来检索与您传入的友好名称关联的CRecordsetEx
对象。CODBCAccess::GetSet
是重载的,因此有两种获取记录集指针的方法。第一种方法是向函数传递一个引用参数,该函数将用记录集填充该引用参数;第二种方法是传递友好名称,让函数返回指向所需记录集的指针。示例调用如下:
//Passing an existing pointer for the function to fill: CRecordsetEx *setPtr; myDB.GetSet("MyNewSet", setPtr); //Getting a pointer from the function: CRecordsetEx *setPtr = myDB.GetSet("MyNewSet");
如果您有记录集指针,您可以对该指针执行任何您想执行的函数。您甚至可以关闭并重新打开该记录集。但是,重要的是您_不要_删除指针位置的数据,因为CODBCAccess
会管理这些指针的列表。要关闭并释放记录集使用的内存,请调用CODBCAccess::CloseSet
函数,例如以下示例:
//Closes the set if it is open and deletes the memory used by the object: myDB.CloseSet("MyNewSet");
CODBCAccess
提供了几个函数来处理两个特殊的记录集:一个用于枚举打开数据库中的所有表,另一个用于枚举打开数据库中给定表的所有列。承 George Polouse和他出色的ODBC交互式SQL工具的恩惠,CColumns
和CTables
类被CODBCAccess
使用以实现此目的。要打开一个枚举打开数据库中表的记录集,请调用CODBCAccess::QueryOpenTables
,如下所示:
myDB.QueryOpenTables();调用该函数后,您可以调用
CODBCAccess::GetTables
来获取记录集的指针。同样,此函数有两个重载,如下所示://Passing an existing pointer for the function to fill: CTables *tablesPtr; myDB.GetTables(tablesPtr); //Getting a pointer from the function: CTables *tablesPtr = myDB.GetTables();要枚举指定表中的列,您必须调用函数
CODBCAccess::QueryOpenColumns
并传入要查询的表名:myDB.QueryOpenColumns("Main");
调用该函数后,您可以使用CODBCAccess::GetColumns
函数获取记录集的指针,该函数也有两个重载://Passing an existing pointer for the function to fill: CColumns *colsPtr; myDB.GetColumns(colsPtr); //Getting a pointer from the function: CTables *colsPtr = myDB.GetColumns();关于查询表和列的最后一点说明。因为您可能需要为多个表名/数据库查询列/表,所以没有像记录集那样用于“关闭”这些对象的函数
CODBCAccess::CloseSet
。这是因为内存总是在数据库关闭时被释放,并且如果您想打开一组新的列或表,该集合会被重用。您所需要做的就是再次调用QueryOpenTables或QueryOpenColumns来重新查询一组新的表或列。当您完成数据库使用后,可以调用CODBCAccess::Disconnect
关闭与数据库的连接并释放所有与记录集相关的内存。CODBCAccess::Disconnect
会自动由类的析构函数调用(当对象超出作用域时调用)。
为什么所有东西都要两步操作?!(关于错误检查的说明)
我希望CODBCAccess
能够处理ODBC数据库带来的所有烦人的错误检查,因此我设计了类中几乎所有执行数据库操作或从数据库返回数据的函数都返回一个布尔值,指示函数是失败还是成功。类中任何返回布尔值并且操作数据库或从数据库获取内容的函数都会设置两个错误变量,指示函数的结果。这两个变量中的每一个都可以用来找出出了什么问题。无论函数成功还是失败,这两个变量始终会为上次调用的函数设置。一个变量是错误代码变量(有关代码的说明,请参阅下面的函数列表),另一个是包含错误说明的CString
。您可以通过调用以下两个函数来获取每个变量:
//To get the error code: int code = myDB.GetLastErrCode(); //To get the error string: CString errorString = myDB.GetLastErrMsg();
由于几乎每个函数都对几乎所有内容进行错误检查,因此许多操作都采用两步过程;例如,获取记录集的过程。对于那些无法忍受浪费一行代码声明一个引用参数的指针的人(比如我自己=),我重载了集合函数,让您在两步过程或一步过程之间进行选择。如果您选择一步过程,我建议您检查返回的指针/对象是否为NULL。如果您使用两步过程,您可以检查函数是否返回false(在这种情况下,您提供的指针将始终为NULL),然后分析错误代码。
类中的函数
CODBCAccess::CODBCAccess
描述:类构造函数。
返回值:无。
附加信息:构造函数仅设置几个内部变量,因此您需要单独连接到数据源。
CODBCAccess::CODBCAccess();
CODBCAccess::~CODBCAccess
描述:类析构函数。
返回值:无。
附加信息:析构函数始终调用CODBCAccess::Disconnect
。
CODBCAccess::~CODBCAccess();
CODBCAccess::ConfigDataSource
描述:以编程方式添加、修改或删除数据源。
返回值:布尔值,指示成功或失败。
附加信息:两个重载,一个提供Microsoft Access驱动程序数据源配置,另一个提供通用驱动程序数据源配置。
//(Overload 1) BOOL CODBCAccess::ConfigDataSource( UINT nOperation, //What you want to do to the data source const CString &sDSN, //The data source name (e.g "Payroll") const CString &sDatabase, //The absolute path of the database BOOL bConnectAfter, //Connects to the data source you just configured const CString &sDescription = "", //Optional: description of data source BOOL bReadOnly = false, //Optional: read only access BOOL bExclusive = false); //Optional: one user at a time access //(Overload 2) BOOL CODBCAccess::ConfigDataSource( UINT nOperation, //What you want to do to the data source const CString &sDriver, //The driver name const CString &sAttributes); //The attributes for the driver注意:
UINT nOperation
是以下三项之一:DATASOURCE_ADD、DATASOURCE_MOD或DATASOURCE_DEL,分别用于添加、修改和删除数据源。CODBCAccess::Connect
描述:连接到数据源。
返回值:布尔值,指示成功或失败。
附加信息:两个重载,一个允许您提供连接信息,另一个将显示ODBC对话框让用户选择数据源。
//(Overload 1) BOOL CODBCAccess::Connect( const CString &sDSN, //The data source name (e.g. "Payroll") const CString &sID = "", //User ID for the database const CString &sPass = "", //Password for the database BOOL bExclusive = false, //Exclusive access BOOL bReadOnly = false); //Read only access //(Overload 2) BOOL CODBCAccess::Connect();
CODBCAccess::IsConnected
描述:告诉您是否已连接到数据库。
返回值:布尔值,指示已连接或未连接。
附加信息:无。
BOOL CODBCAccess::IsConnected();
CODBCAccess::CreateDatabase
描述:创建一个新的*.mdb文件,并可以选择配置数据源并连接到它。
返回值:布尔值,指示成功或失败。
附加信息:这对于创建临时数据库或以编程方式完全控制数据库很有用。
BOOL CreateDatabase( const CString &sFileName, //The filename of the new database (must
//contain '.mdb' extension) BOOL bConfigDataSource = false, //Configures a datasource for the
// just-created datasource const CString &sDSN = "", //The data source name (e.g. "Payroll") BOOL bConnectAfter = false, //Connects to the data source you just
// configured const CString &sDescription = "", //Optional: description of data source BOOL bReadOnly = false, //Optional: read only access BOOL bExclusive = false); //Optional: one user at a time access
CODBCAccess::SetTimeouts
描述:设置连接和查询数据库的超时秒数。
返回值:void。
附加信息:无。
void CODBCAccess::SetTimeouts( int nLoginSeconds, //# of seconds for login timeout int nQuerySeconds); //# of seconds for query timeout
CODBCAccess::Disconnect
描述:断开与数据源的连接并释放内存。
返回值:void。
附加信息:如果数据库已关闭,则该函数不执行任何操作。
void CODBCAccess::Disconnect();
注意:Disconnect将释放数据源连接生命周期内分配的所有内存。调用CODBCAccess
析构函数时,也会始终调用该函数。
CODBCAccess::StartTransaction
描述:开始数据库事务。有关事务的信息,请在MSDN库中搜索CDatabase::BeginTrans
。
返回值:布尔值,指示成功或失败。
附加信息:如果您已经在事务中,则该函数将失败。
BOOL CODBCAccess::StartTransaction();
CODBCAccess::SendSQL
描述:向数据库发送SQL语句。
返回值:布尔值,指示成功或失败。
附加信息:如果您在事务中,则执行的SQL语句将可以被撤销。
BOOL CODBCAccess::SendSQL(const CString &sSQL);
CODBCAccess::Rollback
描述:结束数据库事务,但撤销在事务期间所做的任何更改。
返回值:布尔值,指示成功或失败。
附加信息:无。
BOOL CODBCAccess::Rollback();
CODBCAccess::EndTransaction
描述:结束数据库事务,从而锁定您在事务期间所做的任何更改。
返回值:布尔值,指示成功或失败。
附加信息:如果CDatabase::CommitTrans
因任何原因失败,该函数将尝试回滚所做的更改。
BOOL CODBCAccess::EndTransaction();
CODBCAccess::IsInTrans
描述:告诉您是否处于事务中。
返回值:布尔值,指示是否处于事务中。
附加信息:无。
BOOL CODBCAccess::IsInTrans();
CODBCAccess::GetCDatabase
描述:返回由类管理的CDatabase对象。
返回值:CDatabase指针。
附加信息:_切勿_关闭或删除该对象。
CDatabase *CODBCAccess::GetCDatabase();
CODBCAccess::GetLastErrCode
描述:返回最后一个错误代码。
返回值:表示最后一个错误代码的int
。
附加信息:无。
int CODBCAccess::GetLastErrCode();
注意:返回的代码可以是以下五种之一:RETURN_SUCCESS
(函数成功);RETURN_ARGUMENT
(传递给函数的参数有问题);RETURN_ERRMSG
(检查GetLastErrMsg
以找出问题所在);RETURN_DB
(数据库未打开);RETURN_CRITICAL
(遇到严重错误,为安全起见已关闭数据库)。
CODBCAccess::GetLastErrMsg
描述:返回最后一条错误消息。
返回值:表示最后一条错误消息的CString
。
附加信息:无。
CString CODBCAccess::GetLastErrMsg();
CODBCAccess::OpenNewSet
描述:根据传入的值创建/打开一个由您使用的友好名称标识的新记录集。
返回值:布尔值,指示成功或失败。
附加信息:OpenNewSet
将管理记录集的创建。
BOOL CODBCAccess::OpenNewSet( const CString &sFriendlyName, //the name by which to reference this set const CString &sSQL = _T(""), //the SQL statement to execute for the set const CString &sTableName = _T("")); //OR the table name
注意:如果希望函数正常工作,请仅指定SQL语句或表名,而不是两者都指定=)
CODBCAccess::CloseSet
描述:关闭并释放关联记录集的内存。
返回值:布尔值,指示成功或失败。
附加信息:无。
BOOL CODBCAccess::CloseSet(const CString &sFriendlyName);
//the name of the set (assigned on opening)
CODBCAccess::CloseAllSets
描述:关闭并释放所有打开记录集的内存。
返回值:布尔值,指示成功或失败。
附加信息:无。
BOOL CODBCAccess::CloseAllSets();
CODBCAccess::GetSet
描述:检索指向关联记录集的指针。
返回值:布尔值,指示成功或失败,或指向记录集的指针。
附加信息:两个重载:第一个是两步过程,您通过引用传递一个指针,函数将填充该指针;第二个返回指向关联CRecordsetEx
对象的指针。
//(Overload 1) BOOL CODBCAccess::GetSet( const CString &sFriendlyName, //the name of the set (assigned on opening) CRecordsetEx *&dyna); //the pointer to recieve the set address //(Overload 2) CRecordsetEx *CODBCAccess::GetSet( const CString &sFriendlyName); //the name of the set (assigned on opening)
CODBCAccess::GetNamesOfOpenSets
描述:将所有打开记录集的友好名称填充到传入的CStringArray
中。
返回值:void。如果数据库未打开或存在其他问题,则CStringArray
将为空。
附加信息:无。
void CODBCAccess::GetNumberOfOpenSets(CStringArray &array);
//The array to be filled with the names
CODBCAccess::GetNumSets
描述:获取类管理的集合数量。
返回值:管理的集合数量。
附加信息:无。
int CODBCAccess::GetNumSets();
CODBCAccess::QueryOpenTables
描述:打开一个记录集,该记录集枚举(每行一个)打开数据库中的表。
返回值:布尔值,指示成功或失败。
附加信息:此函数可以连续调用多次,而无需关闭记录集。
BOOL CODBCAccess::QueryOpenTables();
CODBCAccess::QueryOpenColumns
描述:打开一个记录集,该记录集枚举(每行一个)指定表中的列。
返回值:布尔值,指示成功或失败。
附加信息:此函数可以连续调用多次,而无需关闭记录集。
BOOL CODBCAccess::QueryOpenColumns(const CString &sTableName); // the name of the table to get columns from
CODBCAccess::GetTables
描述:获取枚举表的记录集(作为CTables
指针)。
返回值:布尔值,指示成功或失败,或指向CTables
的指针。
附加信息:两个重载:第一个是您通过引用传递一个指针,函数将填充该指针;第二个返回指向CTables
指针的指针。
//(Overload 1) //the pointer to recieve the set address BOOL CODBCAccess::GetTables(CTables *&table);
//(Overload 2) CTables *CODBCAccess::GetTables();
CODBCAccess::GetColumns
描述:获取枚举列的记录集(作为CColumns
指针)。
返回值:布尔值,指示成功或失败,或指向CColumns
的指针。
附加信息:两个重载:第一个是您通过引用传递一个指针,函数将填充该指针;第二个返回指向CColumns
指针的指针。
//(Overload 1) //the pointer to recieve the set address BOOL CODBCAccess::GetColumns(CColumns *&cols); //(Overload 2) CColumns *CODBCAccess::GetColumns();
致谢
特别感谢George Polouse编写出色的“ODBC交互式SQL工具”,并允许我在我的类中使用他的类。
结论
我想快速说明一下这个类。我知道代码中会有bug。如果您发现bug,可以通过发送电子邮件至Alexander@wisemanweb.com告知我。另外,我已尽最大努力根除任何内存泄漏,但可能仍有一些。如果您发现内存泄漏,请_务必_告诉我,因为我想使这个类尽可能有用且无bug。感谢您花时间阅读我的文章,希望这个类对您有所帮助!
历史
- 2002年3月6日 - 更新下载
- 2002年6月12日 - 更新下载