ActiveX Data Objects (ADO) 通过 OLE DB 访问和操作数据库,OLE DB是一组”组件对象模型”(COM) 接口,封装了ODBC的功能。相比MFC封装的ODBC类,使用ADO可以对数据库进行更高效、更灵活访问。
实现步骤(以SQL SERVER为例)
1、安装数据库,设置访问用户和密码,新建数据库和数据表
关于SQL SERVER安装和使用可以参考相关文档。
2、在MFC中使用ADO
首先,引入ADO库文件
在stdafx.h (预编译头文件),或者自建的ADO类头文件中添加代码:
#import "C:\Program Files\Common Files\System\ado\msado15.dll" no_namespace rename("EOF","adoEOF")
然后,在使用ADO 前,初始化OLE/COM库环境,
CoInitialize(NULL);
初始化 _ConnectionPtr _RecordsetPtr 和 _CommandPtr 三个接口,调用相应的功能实现数据库访问(前面两个接口就可以完成数据库的大部分操作)。
优点:
MFC的ODBC类绑定每张表,意味着新建一张表就需要创建一个记录集类来访问;而ADO利用_RecordsetPtr (_CommandPtr )执行SQL语句来实现数据库的CURD操作。
缺点:
ADO相对来说比较复杂,尤其是COM中使用的VARIANT和BSTR数据类型 , 以及和他们相应的两个类 _variant_t 、_bstr_t 。
3、实现
新建类 CAdoSqlServer
头文件
#pragma once
#import "C:\Program Files\Common Files\System\ado\msado15.dll" no_namespace rename("EOF","adoEOF")
#include <vector>
using namespace std;
class CAdoSqlServer
{
private:
_ConnectionPtr m_Connection;
_RecordsetPtr m_DataSet;
bool isInit;
CAdoSqlServer(void);
~CAdoSqlServer(void);
public:
static CAdoSqlServer* GetInstance()
{
static CAdoSqlServer m_sinstance;
return &m_sinstance;
}
bool Init(CString serverName,CString dataBaseName,CString useName,CString passWord,CString &errStr);
void Select(CString sql,vector<vector<CString> > &resultVector);
};
其中设计思路:使用单例模式对数据库访问、通过Init函数配置数据库信息、数据表的查询直接返回二维的向量vector (第一行是数据表字段,后续行是记录)
CPP文件
#include "stdafx.h"
#include "AdoSqlServer.h"
//CAdoSqlServer* CAdoSqlServer::pInstance=NULL;
CAdoSqlServer::CAdoSqlServer(void):isInit(false),m_Connection(NULL),m_DataSet(NULL)
{
CoInitialize(NULL);
}
CAdoSqlServer::~CAdoSqlServer(void)
{
CoUninitialize();
}
bool CAdoSqlServer::Init(CString serverName,CString dataBaseName,CString useName,CString passWord,CString &errStr)
{
if(m_Connection==NULL && FAILED(m_Connection.CreateInstance("ADODB.Connection")))
{
errStr = TEXT("ADODB.Connection Init error");
return false;
}
if(m_DataSet==NULL && FAILED(m_DataSet.CreateInstance("ADODB.Recordset")))
{
errStr = TEXT("ADODB.Recordset Init error");
return false;
}
CString strSRC;
strSRC="Driver=SQL Server;Server=";
strSRC+=serverName;
strSRC+=";Database=";
strSRC+=dataBaseName;
strSRC+=";UID=";
strSRC+=useName;
strSRC+=";PWD=";
strSRC+=passWord;
_bstr_t bstrSRC(strSRC);
if (FAILED(m_Connection->Open(bstrSRC,"","",-1)))
{
errStr = TEXT("Can not open Database!");
return false;
}
return isInit = true;
}
void CAdoSqlServer::Select(CString sql,vector<vector<CString> > &resultVector)
{
m_DataSet->Open(sql.GetBuffer(0),m_Connection.GetInterfacePtr(),adOpenDynamic,adLockOptimistic,adCmdUnknown);
FieldsPtr ft;
ft = m_DataSet->Fields;
vector<_bstr_t> th;
vector<CString> tmp;
_bstr_t bs;
for(int i=0; i< ft->GetCount();i++)
{
CString tmpStr;
bs =ft->GetItem(_variant_t((long)i))->Name;
th.push_back(bs);
tmpStr=(LPCSTR)(bs);
tmp.push_back(tmpStr);
}
int s;
if((s=th.size()) == 0) return;
resultVector.push_back(tmp);
while(!m_DataSet->adoEOF)
{
tmp.clear();
for(int i=0;i<s;i++)
{
if(m_DataSet->GetCollect(th[i]).vt !=VT_NULL)
{
CString tmpStr;
bs = m_DataSet->GetCollect(th[i]);
tmpStr=(LPCSTR)(bs);
tmp.push_back(tmpStr);
}
else tmp.push_back(TEXT(""));
}
resultVector.push_back(tmp);
m_DataSet->MoveNext();
}
}
字符串的 L 和 TEXT 可以通过设置工程属性为多字节来省略。
该类的使用相对来说比较容易,示例代码:
CAdoSqlServer* instance=CAdoSqlServer::GetInstance();
CString cs=L"";
instance->Init(TEXT("******"),TEXT("******"),TEXT("******"),TEXT("******"),cs);
//填入信息:服务器名、数据库、用户名、密码
//此处可以通过cs来获取连接中是否有错误
vector<vector<CString> > resultVector;
instance->Select(L"select top 10 * from TagsTable",resultVector);
// SQL语句
//返回查询集,包含表头,简单粗暴!