65.9K
CodeProject 正在变化。 阅读更多。
Home

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

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.94/5 (10投票s)

2013年5月8日

Ms-PL

3分钟阅读

viewsIcon

48189

downloadIcon

3319

这是“一套 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 supCleanCMDvoid supCleanRSvoid 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
© . All rights reserved.