一套用于 ADO 的 MFC 包装类 - 版本 2.20J






4.94/5 (10投票s)
这是“一套 ADO 类 - 版本 2.20”的一个替代方案
引言
这是我对 Carlos Antollini 出色的 ADO 类集进行的一次小更新。虽然这可能比 .NET 类不那么常见,但 MFC 仍然被广泛使用,我希望这些更改能对某些人有所帮助。
背景
该类最初发布于 2005 年,未考虑 64 位数据和编译器。我已经添加了对 64 位数据的支持,例如 MS-SQL 的 BIGINT
。我还支持 64 位二进制数据到 64 位整数的转换,这在我们需要读取 MS-SQL 的 ROWVERSION 和类似类型的字段时非常有用。
我还添加了一些实用函数,使常用任务成为类的一部分。但大部分我保留了原始代码,并确保保持向后兼容性。
当然,所有这些都旨在作为 32 位应用程序进行编译。如果需要,我稍后可能会为 64 位应用程序添加更多内容。
您可能还需要为某些操作系统获取新的 TLB。它包含在此文章中,也可以从 Microsoft 获取。(msado60_Backcompat_i386.tlb)
Using the Code
在本节中,我不会重复 Carlos 在其 原始帖子 中详细描述的内容,而是专注于我的更改。
为宿主操作系统调整头文件
根据宿主操作系统的位数,会使用不同版本的 ADO。如果需要,请确保在包含头文件之前定义此值。
#define _USE_WINX86_FOLDER_ //Use this when compiling on 64 bit PC
#include <ado2.h> //ADO wrapper class
新功能
首先,支持 **64 位**数据
GetFieldValue
函数返回一个包含字段值的值。
BOOL GetFieldValue(LPCTSTR lpFieldName, INT64& lValue);
BOOL GetFieldValue(int nIndex, INT64& lValue);
BOOL GetFieldValue(LPCTSTR lpFieldName, UINT64& ulValue);
BOOL GetFieldValue(int nIndex, UINT64& ulValue);
SetFieldValue
函数设置字段的值。
BOOL SetFieldValue(int nIndex, INT64 lValue);
BOOL SetFieldValue(LPCTSTR lpFieldName, INT64 lValue);
BOOL SetFieldValue(int nIndex, UINT64 lValue);
BOOL SetFieldValue(LPCTSTR lpFieldName, UINT64 lValue);
新的实用函数
以下是我包装常用任务的新实用函数。
CADODatabase
类拥有一组与 _ConnectionPtr
相对应的函数。我向此类添加了以下函数:
bool supIsValidDBPtr
- 如果对象已初始化并准备好使用,则返回true
- 对于一个新指针
(CADODatabase* pDB)
,pDB->supIsValidDBPtr()
应返回false
- 对于一个已初始化的新指针
(pDB = new CADODatabase)
,pDB->supIsValidDBPtr()
应返回true
- 对于一个新指针
bool supReopenDB
- 尝试关闭并重新打开数据库,并通过“SELECT 1
”记录集进行测试以确保连接性bool supIsDBAccessible
- 测试当前 DB 对象是否可以访问,并可选择使用“SELECT 1
”记录集进行测试或尝试重新打开
CADORecordset
类拥有一组与 _RecordsetPtr
相对应的函数。我向此类添加了以下函数:
- 64 位支持
bool supHasRecord()
- 检查上次查询是否返回任何行的一种简单方法bool supOpenHasRecord()
- 将Open
方法与上面的函数合并为一次调用__int64 supDbRowVersionTo64(LPCSTR pszField)
- 返回 SQL Server ROWVERSION 字段或类似类型数据的 64 位表示
**新**的 CADOTool
类拥有一组包装常用任务的静态实用函数
CADODatabase* pDB = NULL; //Declare a new empty pointer
bool bRc = supInitDatabase(&pDB, szConnectString, 10); //Try to init
bool supInitDatabase
- 接受指向指针的指针,尝试打开连接,然后将宿主指针初始化为一个已初始化的CADODatabase
对象void supCloseDB
- 接受指向指针的指针,安全地关闭数据库并释放资源supCloseDB(&pData->m_pAltDB); //Closes the database if opened and the pointer is valid, //set the host's pointer to NULL on exit
bool supIsValidDBPtr
- 测试传入的CADODatabase
指针,以尽最大努力判断其是否已分配且有效bool supIsValidRSPtr
- 测试传入的CADORecordset
指针,以尽最大努力判断其是否已分配且有效void supCleanCMD
、void supCleanRS
和void supCleanPrm
都会释放相应的资源并将宿主指针设置为 NULL。bool adoBuildConnection
- 显示 ADO 连接向导 UI,如果成功则在传入的CString
中设置组成的连接字符串,如果取消或出错则返回 false。
示例
此示例试图使用一个虚构的数据库演示类的基本用法。
CString csConnect;
CString csSQL;
CADODatabase* pDB = NULL; //Important, set to NULL!!
CADORecordset* pRS = NULL; //Important, set to NULL!!
int iUpdated;
//Fields
__int64 iID;
CString csName;
COleDateTime cdtBirth;
BOOL bActive;
//Build a connect string
if(!CADOTool::adoBuildConnection(csConnect))
{
OutputDebugString("You cancelled the dialog!\n");
return;
}
//Open the database
if(!CADOTool::supInitDatabase(&pDB, csConnect))
{
OutputDebugString("Somehow, the database cannot be opened!\n");
return;
}
//Get some data with this made-up query
csSQL = "SELECT ID, fldName, fldBirth, fldIsActive FROM tblUserData ORDER BY fldMemberDate DESC";
//Use ADO...
try{
if(pRS->supOpenHasRecord(csSQL)) //If we have some data
{
//We are on the first record
do
{
pRS->GetFieldValue("ID", iID);
pRS->GetFieldValue("fldName", csName);
pRS->GetFieldValue("fldBirth", cdtBirth);
pRS->GetFieldValue("fldIsActive", bActive);
//Do something with the data
//Edit something!
pRS->Edit();
pRS->SetFieldValue("fldIsActive", true);
pRS->Update();
pRS->MoveNext(); //Move! Otherwise be caught in an infinite loop!
}while(!pRS->IsEOF());
}
else
{
//What!? Either cannot open or we don't have data
if(pRS->IsOpen())
{
//Add new record
pRS->AddNew();
pRS->SetFieldValue("fldName", CString("First, Last"));
pRS->SetFieldValue("fldBirth", COleDateTime(1980, 10, 2, 0, 0, 0));
pRS->SetFieldValue("fldIsActive", TRUE);
pRS->Update();
pRS->GetFieldValue("ID", iID); //Get our newly created ID
}
}
//Now, let us try a direct query to our fictitious DB
if(pDB->Execute("UPDATE tblManager SET fldLastChech = GETDATE() WHERE ID = 3"))
{
iUpdated = pDB->GetRecordsAffected(); //Get affected records by last query
}
}
catch(CADOException& cEx)
{
OutputDebugString("Oups, got a database error!\n");
OutputDebugString(cEx.GetErrorMessage());
OutputDebugString("\n");
}
//No matter what, clean all!
CADOTool::supCleanRS(&pRS); //Clean resources from our recordset
CADOTool::supCloseDB(&pDB); //Release our DB
历史
- 2013 年 5 月 7 日 - 我贡献的代码的首次发布,基于原始的 2.20 版本
- 2013 年 5 月 15 日 - 添加了示例并修复了一个函数错误(
supOpenHasRecord
)