最近学习使用数据库,开始使用的ADO,后来改用ODBC。现在将自己写的结合网上的ADO写了一个简单的封装类。
#pragma once
class CDBOperator
{
public:
CDBOperator(void);
~CDBOperator(void);
// 打开数据库连接 输入DSN名称、用户和密码
BOOL OpenDataBase(CString strDsnName, CString strUserID, CString strPassword);
// 执行SQL查询语句,结果放在数据pData中
// 执行失败返回值<0,可通过GetErrorMessage获得出错信息
int Select(CString strSql);
// 执行sql语句
// 执行失败返回值<0,可通过GetErrorMessage获得出错信息
int Excute(CString strSql);
// 关闭数据库连接
BOOL CloseDataBase();
// 获取错误信息
CString GetErrorMessage();
public:
int m_nResultRow; // 查询结果行数
int m_nResultCol; // 查询结果列数
CStringArray m_pData; // 将查询结果全部转换为字符串 大小nRow*nCol
// m_pData[i*m_nResultCol+j];
CString m_strErrorMessage; // 出错信息
//private:
_ConnectionPtr m_pConnection; // 数据库连接指针
_RecordsetPtr m_pRecordset; // 记录集
CString m_strDsnName; // 连接字符串
CString m_strUserID; // 用户ID
CString m_strPassword; // 密码
};
下面是实现
#include "StdAfx.h"
#include "DBOperator.h"
CDBOperator::CDBOperator(void)
: m_pConnection(NULL)
, m_pRecordset(NULL)
, m_nResultRow(0)
, m_nResultCol(0)
{
}
CDBOperator::~CDBOperator(void)
{
if ( m_pRecordset )
{
m_pRecordset->Close();
m_pRecordset = NULL;
}
if ( m_pConnection )
{
m_pConnection->Close();
m_pConnection = NULL;
}
}
BOOL CDBOperator::OpenDataBase(CString strDsnName,
CString strUserID,
CString strPassword)
{
m_strDsnName = strDsnName;
m_strUserID = strUserID;
m_strPassword = strPassword;
CoInitialize(NULL);
m_pConnection.CreateInstance(__uuidof(Connection));
try
{
m_pConnection->ConnectionTimeout = 5;
HRESULT hr = m_pConnection->Open((_bstr_t)strDsnName, (_bstr_t)strUserID, (_bstr_t)strPassword, adModeUnknown);
//HRESULT hr = m_pConnection->Open("DSN=MySqlODBC;Server=localhost;database=mes","root","123456",adModeUnknown);
}
catch (_com_error& e)
{
m_strErrorMessage = (LPCTSTR)e.Description();
return FALSE;
}
return TRUE;
}
int CDBOperator::Select(CString Sql)
{
if ( m_pRecordset != NULL )
{
m_pRecordset->Close();
m_pRecordset = NULL;
}
// 创建记录集对象实例
int i = 0, j = 0;
HRESULT hr = m_pRecordset.CreateInstance("ADODB.Recordset");
if ( !SUCCEEDED(hr) )
{
m_strErrorMessage = _T("Recordset CreateInstance failed!");
return -1;
}
try
{
// 打开记录集
hr = m_pRecordset->Open(Sql.GetBuffer(Sql.GetLength()),
_variant_t((IDispatch*)m_pConnection, true),
adOpenUnspecified, adLockUnspecified, adCmdText);
// 获得记录集总列数
m_nResultCol = m_pRecordset->Fields->GetCount();
if ( m_pRecordset->adoEOF )
{
return 0;
}
else
{
m_pRecordset->MoveFirst();
}
while ( !m_pRecordset->adoEOF )
{
_variant_t vValue, vValue1;
CString str;
// 取一列数据
for ( j=0; j<m_nResultCol; j++ )
{
str.Empty();
// 取得当前记录字段数据
vValue = m_pRecordset->Fields->Item[(long)j]->Value;
// 数据非空
if ( vValue.vt != 1 )
{
int type = vValue.vt;
// 转换数据类型(为字符串)
if (VariantChangeType(&vValue1, &vValue, 0, VT_BSTR) == S_OK )
{
str = vValue1.bstrVal;
}
}
// 动态设置数值大小
if (m_pData.GetSize()<i*m_nResultCol+j+1)
{
m_pData.SetSize(i*m_nResultCol+j+1);
}
// 保存结果到数组中
m_pData[i*m_nResultCol+j] = str;
}
// 移动记录集指针到下一行
m_pRecordset->MoveNext();
i++;
}
m_pRecordset->Close();
m_pRecordset = NULL;
m_nResultRow = i;
}
catch (_com_error e) // 捕捉异常
{
m_strErrorMessage = (LPCTSTR)e.Description();
m_pRecordset = NULL;
return -1;
}
// 释放多余的内存空间
m_pData.FreeExtra();
return m_nResultRow;
}
int CDBOperator::Excute(CString Sql)
{
_variant_t RecordsAffected;
try
{
// 是否已经连接数据库
if(m_pConnection == NULL)
{
m_strErrorMessage = _T("empty database!");
return -1;
}
// Connection对象的Execute方法:(_bstr_t CommandText,
// VARIANT * RecordsAffected, long Options )
// 其中CommandText是命令字串,通常是SQL命令。
// 参数RecordsAffected是操作完成后所影响的行数,
// 参数Options表示CommandText的类型:adCmdText-文本命令;adCmdTable-表名
// adCmdProc-存储过程;adCmdUnknown-未知
_RecordsetPtr hr = m_pConnection->Execute((_bstr_t)Sql, &RecordsAffected, adCmdText);
return 1;
}
catch(_com_error e)
{
m_strErrorMessage = (LPCTSTR)e.Description();
return -1;
}
}
CString CDBOperator::GetErrorMessage()
{
return m_strErrorMessage;
}
BOOL CDBOperator::CloseDataBase()
{
if ( m_pRecordset )
{
m_pRecordset->Close();
m_pRecordset = NULL;
}
if ( m_pConnection )
{
m_pConnection->Close();
m_pConnection = NULL;
}
m_pData.RemoveAll();
return TRUE;
}
该封装主要是把从数据库中读出来的数据全转变为字符串了。可以自己操纵_variant_t去进行具体的转换。。。
当然别忘了在StdAfx.h文件中添加如下代码
#import "msadox.dll"
#import "msado15.dll" no_namespace rename("EOF", "adoEOF")