VC++使用ADO方法读写Microsoft Access本地数据库文件(不用ODBC)

本文出处:   http://blog.csdn.net/word_world/article/details/9738407

特点:

像对待文件一样创建/读/写Access数据库,无须创建数据源.

说明:

作者为此写了一个类FAdoDbHandler,其声明和实现分别放在FAdoDbHandler.h和FAdoDbHandler.cpp文件中,测试代码置于main.cpp中.

以下代码在VC++6.0下测试通过(控制台应用程序  项目设置中使用MFC)

Access 版本为 2003

/*┏━━━━━━━━━━━━━━━━━━━┓
  ┃  文件名: FAdoDbHandler.h            ┃
  ┣━━━━━━━━━━━━━━━━━━━┫
  ┃  描  述: FAdoDbHandler 类的声明     ┃
  ┣━━━━━━━━━━━━━━━━━━━┫
  ┃  更新日期:2013-08-01              ┃
  ┗━━━━━━━━━━━━━━━━━━━┛*/
#ifndef __FADODBHANDLER_HEADER__
#define __FADODBHANDLER_HEADER__

#include <iostream>
#include <vector>

#import "C:/Program Files/Common Files/System/ado/msadox.dll"							//no_namespace //ADOX
#import "C:/Program Files/Common Files/System/ado/msado15.dll"  rename("EOF","adoEOF")	// no_namespace // 不使用命名空间 ADODB
//#pragma warning (disable:4146)
//#pragma warning (default:4146)
class FAdoDbHandler
{

protected:// 类成员
	static const std::string ACCESS_PROVIDER;	// Access数据库驱动程序
	static bool _bInitialized;					// COM环境已初始化标志
	static std::vector<FAdoDbHandler*> * _dbHandlers;
protected:// 对象成员
	ADOX::_CatalogPtr _pCatalog;				// 数据库智能指针
	ADODB::_ConnectionPtr _pConnection;			// 连接智能指针
	ADOX::_TablePtr _pTable;					// 表指针
	//ADODB::_RecordsetPtr _pRecordset;			// select结果记录集

	std::string _dbFullPathName;				// 完整路径数据库名
	std::string _dbNameWithProvider;			// 带驱动程序名的数据库名

public:// 静态成员函数
	// 创建一个FAdoDbHandler对象
	static FAdoDbHandler * CreateHandler();
	// 清理FAdoDbHandler对象
	static void CleanUp();

public:// 非静态成员函数
	bool CreateDatabase(char* dbFullPathName);	// 创建数据库
	bool ConnectDatabase(char* dbFullPathName);	// 连接数据库
	bool Connect();								// 连接当前数据库
	void Disconnect();							// 断开当前数据库的连接
	bool ExistTable(char* tbName);				// 判断表是否在当前数据库中存在
	int  CreateTable(char* tbName,char* szSQL);	// 在当前数据库中创建表
	int  ExecuteNonQuery(char* szSQL);			// 执行insert update delete语句
	ADODB::_RecordsetPtr ExecuteQuery(char* szSQL);// 执行 select 语句

protected:// 隐藏构造函数
	FAdoDbHandler();
	virtual ~FAdoDbHandler();

protected:// 辅助函数
	// 生成带驱动程序的数据库名
	static std::string FormatDbNameWithProvider(char* dbFullPathName);

};

#endif

/*┏━━━━━━━━━━━━━━━━━━━┓
  ┃  文件名: FAdoDbHandler.cpp          ┃
  ┣━━━━━━━━━━━━━━━━━━━┫
  ┃  描  述: FAdoDbHandler 类的实现     ┃
  ┣━━━━━━━━━━━━━━━━━━━┫
  ┃  更新日期:2013-08-01              ┃
  ┗━━━━━━━━━━━━━━━━━━━┛*/
#include "FAdoDbHandler.h"

/*┏━━━━━━━━━━━━━━━━━━━┓
  ┃    静态成员                          ┃
  ┗━━━━━━━━━━━━━━━━━━━┛*/

// Acess数据库驱动程序
const std::string FAdoDbHandler::ACCESS_PROVIDER = "Microsoft.Jet.OLEDB.4.0";
// COM环境是否已经初始化
bool FAdoDbHandler::_bInitialized = false;
// FAdoDbHandler池
std::vector<FAdoDbHandler*> * FAdoDbHandler::_dbHandlers = new std::vector<FAdoDbHandler*>();

/************************************************************
 * 获取一个独立的FAdoDbHandler对象指针
 ************************************************************/
FAdoDbHandler* FAdoDbHandler::CreateHandler()
{
	if(!_bInitialized)
	{
		// 初始化 COM 环境
		HRESULT hRe =S_OK;
		hRe = ::CoInitialize(NULL);
		if(!SUCCEEDED(hRe))
		{
			std::cout<<"初始化COM环境失败"<<std::endl;
			return 0;
		}
		_bInitialized = true;
		std::cout<<"初始化COM环境成功"<<std::endl;
	}

	FAdoDbHandler* instance = new FAdoDbHandler();
	// 将新对象加入图中
	_dbHandlers->push_back(instance);

	return instance;
}

/************************************************************
 * 清理FAdoDbHandler对象
 ************************************************************/
void FAdoDbHandler::CleanUp()
{
	if(NULL != _dbHandlers)
	{
		std::vector<FAdoDbHandler*>::iterator itr = _dbHandlers->begin();
		// 销毁全部FAdoDbHandler对象
		while(itr!=_dbHandlers->end())
		{
			delete *itr;
			*itr = 0;
			itr++;
		}
		_dbHandlers->clear();
	}
}


/*┏━━━━━━━━━━━━━━━━━━━┓
  ┃    隐藏构造/析构函数                 ┃
  ┗━━━━━━━━━━━━━━━━━━━┛*/

/************************************************************
 * 构造函数
 ************************************************************/
FAdoDbHandler::FAdoDbHandler()
{
	//_pRecordset = NULL;
	_pTable = NULL;
	_pConnection = NULL;
	_pCatalog = NULL;

	_dbFullPathName = "";
	_dbNameWithProvider = "";

}

/************************************************************
 * 析构函数
 ************************************************************/
FAdoDbHandler::~FAdoDbHandler()
{
	std::cout<<"--------析构函数---------"<<std::endl;
	// 释放智能指针
	//_pRecordset = NULL;
	_pTable = NULL;
	_pConnection = NULL;
	_pCatalog = NULL;

	//断开连接
	Disconnect();

}

/*┏━━━━━━━━━━━━━━━━━━━┓
  ┃    非静态成员函数                    ┃
  ┗━━━━━━━━━━━━━━━━━━━┛*/
/************************************************************
 * 创建数据库 (create database .. )
 * dbFullPathName	: 包含路径名的*.mdb文件名
 * 返回				: true,创建成功; fasle,失败
 ************************************************************/
bool FAdoDbHandler::CreateDatabase(char* dbFullPathName)
{
	// 保存数据库全名 和 带驱动程序名的数据库名
	_dbFullPathName = dbFullPathName;
	_dbNameWithProvider = FormatDbNameWithProvider(dbFullPathName);
	// 创建数据库
	try{
		_pCatalog.CreateInstance(__uuidof (ADOX::Catalog) );	// 获取智能指针实例
		_pCatalog->Create( _bstr_t(_dbNameWithProvider.c_str()) );
		_pCatalog = NULL;										// 释放智能指针
	}
	catch(_com_error & e)
	{
		std::cout<<"创建数据库失败"<<e.ErrorMessage()<<std::endl;
		return false;
	}
	std::cout<<"创建数据库成功"<<std::endl;
	return true;
}

/************************************************************
 * 连接数据库 (use .. )
 * dbFullPathName	: 包含路径名的*.mdb文件名
 * 返回				: true,连接到数据库; fasle,连接失败
 ************************************************************/
bool FAdoDbHandler::ConnectDatabase(char* dbFullPathName)
{
	// 保存数据库全名 和 带驱动程序名的数据库名
	_dbFullPathName = dbFullPathName;
	_dbNameWithProvider = FormatDbNameWithProvider(dbFullPathName);
	// 连接数据库
	Connect();
	return true;
}

/************************************************************
 * 连接当前数据库 (use .. )
 * 返回				: true,连接到数据库; fasle,连接失败
 ************************************************************/
bool FAdoDbHandler::Connect()
{
	try{
		_pConnection = NULL;
		// 实例智能指针
		_pConnection.CreateInstance(__uuidof(ADODB::Connection));
		// 打开连接
		_pConnection->Open(_bstr_t(_dbNameWithProvider.c_str()), "", "", ADODB::adModeUnknown);
	}
	catch( _com_error & err)
	{
		std::cout<<"连接失败"<<err.ErrorMessage()<<std::endl;
		return false;
	}
	std::cout<<"成功连接到数据库"<<std::endl;
	return true;
}

/************************************************************
 * 断开当前数据库的连接
 ************************************************************/
void FAdoDbHandler::Disconnect()
{
	try
	{
		if(NULL!=_pConnection && _pConnection->State)
		{
			_pConnection->Close();	// 关闭连接
			_pConnection = NULL;	// 释放智能指针
		}
		else
		{
			std::cout<<"连接已经断开"<<std::endl;
			return;
		}
	}
	catch(_com_error & err)
	{
		std::cout<<"断开连接异常"<<err.ErrorMessage()<<std::endl;
	}
	std::cout<<"成功断开连接"<<std::endl;
}

/************************************************************
 * 判断表是否在当前数据库中存在
 ************************************************************/
bool FAdoDbHandler::ExistTable(char* tbName)
{
	if(NULL == _pConnection || !_pConnection->State)
		return false;
	_pTable = NULL;
	try{
		_pCatalog.CreateInstance(__uuidof(ADOX::Catalog));
		// 激活db连接,相当于SQL语句use [db_name];
		_pCatalog->PutActiveConnection(_bstr_t(_dbNameWithProvider.c_str())); 
		// 数据库中表总数
		int nTableCnt = _pCatalog->Tables->Count;	
		// 逐表对照表名
		for(int i=0; i<nTableCnt; i++)
		{
			_pTable = (ADOX::_TablePtr)_pCatalog->Tables->GetItem(long(i));
			std::string existTableName = _pTable->Name;
			if(!existTableName.compare(tbName))
				return true;
		}
		_pCatalog = NULL;
	}
	catch(_com_error & err)
	{
		std::cout<<"ExistTable"<<err.ErrorMessage()<<std::endl;
		return false;
	}
	return false;
}

/************************************************************
 * 在当前数据库中创建表 (create table)
 * tbName : 要创建的表名
 * szSQL  : 创建表的SQL语句
 * 返回	  : -1,创建出错; 0,表已经存在; >0,创建成功
 ************************************************************/
int FAdoDbHandler::CreateTable(char* tbName,char* szSQL)
{
	// 检查表是否存在
	if(!ExistTable(tbName))
	{
		if(ExecuteNonQuery(szSQL) >= 0)
			return 1;	// 成功
		else
			return -1;	// 创建出错
	}
	return 0;			// 表已存在
}

/************************************************************
 * 执行不返回记录集的命令 (insert update delete)
 * szSQL: 要执行的SQL语句
 * 返回: >=0 执行完此SQL语句受影响的记录行数
 *		 < 0 出错
 ************************************************************/
int  FAdoDbHandler::ExecuteNonQuery(char* szSQL)
{
	_variant_t nRecordsAffected;	// 受影响的记录数
	try{
		_pConnection->Execute(_bstr_t(szSQL), &nRecordsAffected, ADODB::adModeUnknown);
	}
	catch( _com_error & err)
	{
		std::cout<<"ExecuteNonQuery出错"<<err.ErrorMessage()<<std::endl;
		return -1;
	}
	std::cout<<"ExecuteNonQuery成功"<<std::endl;
	return nRecordsAffected.intVal;
}

/************************************************************
 * 执行返回记录集的命令 (select)
 * szSQL: 要执行的SQL语句
 * 返回: 结果记录集智能指针
 ************************************************************/
ADODB::_RecordsetPtr  FAdoDbHandler::ExecuteQuery(char* szSQL)
{
	_variant_t nRecordsAffected;
	ADODB::_RecordsetPtr rcdset = NULL;
	try{
		rcdset.CreateInstance("ADODB.Record");				// 初始化记录集智能指针实例
		rcdset = _pConnection->Execute(	_bstr_t(szSQL), 
										&nRecordsAffected, 
										ADODB::adCmdText);	// 执行select语句
	}
	catch( _com_error & err)
	{
		std::cout<<"ExecuteQuery失败"<<err.ErrorMessage()<<std::endl;
		return NULL;
	}
	std::cout<<"ExecuteQuery成功"<<std::endl;

	// 返回结果记录集
	return rcdset;
}


/*┏━━━━━━━━━━━━━━━━━━━┓
  ┃    辅助函数                          ┃
  ┗━━━━━━━━━━━━━━━━━━━┛*/

/************************************************************
 * 生成带驱动程序的数据库名
 ************************************************************/
std::string FAdoDbHandler::FormatDbNameWithProvider(char* dbFullPathName)
{
	std::string str = "Provider=";
	str.append(ACCESS_PROVIDER);
	str.append(";Data Source=");
	str.append(dbFullPathName);
	return str;
}

/*┏━━━━━━━━━━━━━━━━━━━┓
  ┃  文件名: main.cpp                   ┃
  ┣━━━━━━━━━━━━━━━━━━━┫
  ┃  描  述: 程序入口                   ┃
  ┣━━━━━━━━━━━━━━━━━━━┫
  ┃  更新日期:2013-08-01              ┃
  ┗━━━━━━━━━━━━━━━━━━━┛*/
#include "fstone/db/ado/FAdoDbHandler.h"

int main()
{
	FAdoDbHandler * db = FAdoDbHandler::CreateHandler();
	
	db->CreateDatabase("database\\db1.mdb");
	db->Connect();

	//db->ConnectDatabase("database\\db1.mdb");

	char * szSql = "create table test3(id int,namestr char(8));";
	int n = db->CreateTable("test3",szSql);
	std::cout<<"建表返回值: "<<n<<std::endl;
	n = db->ExecuteNonQuery("insert into test3(id,namestr)values(15,'Fiftn');");
	//n = db->ExecuteNonQuery("delete from test3");
	std::cout<<"插入返回值: "<<n<<std::endl;
	
	ADODB::_RecordsetPtr result;
	result = db->ExecuteQuery("select * from test3");

	_variant_t tmp;
	try{
		if(NULL != result)
		{
			while( !result->adoEOF )
			{
				tmp = result->GetCollect("id");
				int id = tmp.intVal;
				std::cout<<"id = "<<id<<std::endl;
				tmp = result->GetCollect("namestr");
				std::string name = (_bstr_t)tmp;
				std::cout<<"name = "<<name.c_str()<<std::endl;
				result->MoveNext();
			}
			result->Close();
			result = NULL;
		}
	}
	catch( _com_error & err)
	{
	}

	db->Disconnect();
	
	FAdoDbHandler::CleanUp();
	return 0;
}

  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

游戏AI开发者

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值