在Visual C++或C++ Builder中,我们可以通过访问ADO的COM对象来将对ADO的操作封装成一个类。首先,我们需要对MSADO15.DLL进行导入,让它生成类型库。在C++ Builder中,用TLIBIMP.EXE来生成ADODB_TLB.h,ADODB_TLB.cpp等文件,然后我们通过阅读类型库中的信息,从而可以写成这个类:
.h File
#ifndef ADOH
#define ADOH
#include "ADODB_TLB.h"
#include "utilcls.h"
#include <dstring.h>
class CValue
{
public:
CValue();
~CValue();
Variant m_value;
BOOL AsBool();
String AsString();
int AsInt();
float AsFloat();
TDateTime AsDate();
};
class ADOConnection
{
public:
ADOConnection();
virtual ~ADOConnection();
public:
_ConnectionPtr m_pConnection;
BOOL m_bConnectionOpen;
BOOL m_bInstance;
int m_nOpenMode;
BOOL Open(BSTR dsn,BSTR uid,BSTR pwd);
};
class ADOrecordset
{
public:
ADOrecordset();
virtual ~ADOrecordset();
public:
_ConnectionPtr m_pConnection;
_RecordsetPtr m_recordset;
BOOL m_bOpen;
BOOL SetConnect(_ConnectionPtr _pConnection);
BOOL Open(WideString sql);
HRESULT GetFieldValue(Variant idx,Variant * newVal);
CValue GetFieldValue(String sName);
CValue GetFieldValue(long index);
HRESULT GetFieldCount(long &Count);//added by chenbin
HRESULT GetFields(long index,String& sFieldList);//added by chenbin
HRESULT GetFieldType(FieldPtr pField,String& strMsg,long& nResult);//added by chenbin
HRESULT GetFieldType(String FieldName,String& strMsg,long& nResult);//added by chenbin
BOOL get_BOF();
BOOL get_EOF();
HRESULT Prev();
HRESULT Last();
HRESULT Next();
HRESULT First();
HRESULT CloseRecordset(void);
};
#endif
.cpp File
#ifdef __BORLANDC__
#include <vcl.h>
#pragma hdrstop
#endif
#include "ADO.h"
file://----------Class CValue-------------------
CValue::CValue()
{
file://If necessary,you may add codes here......
}
CValue::~CValue()
{
file://If necessary,you may add codes here.........
}
BOOL CValue::AsBool()
{
if(m_value.IsEmpty()) return false;
else return m_value.AsType(varBoolean);
}
String CValue::AsString()
{
if(m_value.IsEmpty()) return "";
else return m_value.AsType(varString);
}
int CValue::AsInt()
{
int m_int;
if(m_value.IsEmpty()) return 0;
else
{
switch(m_value.Type())
{
case varSmallint:
m_int=m_value.AsType(varSmallint);
break;
case varInteger:
m_int=m_value.AsType(varInteger);
break;
default:
m_int=0;
}
}
return m_int;
}
float CValue::AsFloat()
{
float m_float;
if(m_value.IsEmpty()) return 0;
else
{
switch(m_value.Type())
{
case varSingle:
m_float=m_value.AsType(varSingle);
break;
case varDouble:
m_float=m_value.AsType(varDouble);
break;
default:
m_float=0;
break;
}
}
return m_float;
}
TDateTime CValue::AsDate()
{
file://1970-01-01 12:00:00 is invalid datetime
TDateTime dt=StrToDateTime("1970-01-01 12:00:00");
if(m_value.IsEmpty()) return dt;
else return m_value.AsType(varDate);
}
file://----------------Class ADOConnection------------
ADOConnection::ADOConnection()
{
m_bConnectionOpen= FALSE;
m_bInstance=FALSE;
file://If necessary,you may add codes here....
}
ADOConnection::~ADOConnection()
{
m_bInstance=FALSE;
m_bConnectionOpen=FALSE;
file://If necessary,you may add codes here....
}
BOOL ADOConnection::Open(wchar_t* dsn,wchar_t* uid,wchar_t* pwd)
{
HRESULT hr;
if(!m_bInstance)
{
try
{
hr=m_pConnection.CreateInstance(__uuidof(Connection));
}
catch(Exception &e)
{
::MessageBox(::GetActiveWindow(),e.Message.c_str(),"Error",MB_OK+MB_ICONERROR);
return FALSE;
}
m_bInstance=true;
}
if(m_bConnectionOpen) return TRUE;
try
{
hr=m_pConnection->Open(dsn,uid,pwd,adModeUnknown);
m_nOpenMode=2;
}
catch(Exception &e)
{
::MessageBox(::GetActiveWindow(),e.Message.c_str(),"Error",MB_OK+MB_ICONERROR);
return FALSE;
}
m_bConnectionOpen=TRUE;
hr=S_OK;
return TRUE;
}
file://-------Class ADORecordset------------
ADOrecordset::ADOrecordset()
{
}
ADOrecordset::~ADOrecordset()
{
}
BOOL ADOrecordset::SetConnect(_ConnectionPtr _pConnection)
{
if(_pConnection)
{
HRESULT hr=m_recordset.CreateInstance(__uuidof(Recordset));
m_pConnection=_pConnection;
if(SUCCEEDED(hr)==S_OK) return TRUE;
else return FALSE;
}
else return FALSE;
}
BOOL ADOrecordset::Open(WideString sql)
{
try
{
_CommandPtr m_Cmd("ADODB.Command");
m_Cmd->_set_ActiveConnection(m_pConnection);
m_Cmd->set_CommandText(sql);
m_Cmd->set_CommandType(adCmdText);
m_recordset=m_Cmd->Execute(NULL,NULL,adCmdText);
m_bOpen=true;
}
catch(Exception &e)
{
m_bOpen=FALSE;
return FALSE;
}
return TRUE;
}
HRESULT ADOrecordset::GetFieldValue(Variant idx,Variant * newVal)
{
FieldsPtr *Fields=0;
FieldPtr *Field=0;
HRESULT hr=m_recordset->get_Fields(Fields);
if(hr==S_OK)
{
hr=(*Fields)->get_Item(idx,Field);
if(hr==S_OK)
{
hr=(*Field)->get_Value(*newVal);
}
}
return hr;
}
CValue ADOrecordset::GetFieldValue(String sName)//Get Field's value according to the field's name
{
FieldsPtr *Fields=0;
FieldPtr *Field=0;
CValue v;
Variant idx=sName;
if(m_recordset->get_Fields(Fields)==S_OK)
{
if((*Fields)->get_Item(idx,Field)==S_OK)
{
v.m_value=(*Field)->get_Value();
}
}
return v;
}
CValue ADOrecordset::GetFieldValue(long index)
{
FieldsPtr* Fields=0;
FieldPtr* Field=0;
CValue v;
if(m_recordset->get_Fields(Fields)==S_OK)
{
if((*Fields)->get_Item(index,Field)==S_OK)
{
v.m_value=(*Field)->get_Value();
}
}
return v;
}
HRESULT ADOrecordset::GetFieldCount(long &Count)
{
FieldsPtr* Fields;
HRESULT hr;
hr=m_recordset->get_Fields(Fields);
if(hr==S_OK)
{
hr=(*Fields)->get_Count(&Count);
}
return hr;
}
HRESULT ADOrecordset::GetFields(long index,String& sFieldList)
{
FieldsPtr* Fields;
FieldPtr* Field;
HRESULT hr;
WideString FieldName;
long rec=0;
hr=m_recordset->get_Fields(Fields);
if(hr==S_OK)
{
hr=(*Fields)->get_Count(&rec);
if(hr==S_OK)
{
for(int i=0;i<hr;i++)
{
hr=(*Fields)->get_Item(i,Field);
if(hr==S_OK)
{
hr=(*Field)->get_Name(&FieldName);
if(hr==S_OK)
{
sFieldList+=(String)FieldName;
}
}
}
}
}
return hr;
}
HRESULT GetFieldType(FieldPtr pField,String& strMsg,long& nResult)
{
file://Nowadays I don't use the function,which will be used according to needs in the future
return S_OK;
}
HRESULT GetFieldType(String FieldName,String& strMsg,long& nResult)
{
file://Nowadays I don't use the function,which will be used according to needs in the future
return S_OK;
}
BOOL ADOrecordset::get_BOF()
{
BOOL bFlag=m_recordset->get_BOF();
return bFlag;
}
BOOL ADOrecordset::get_EOF()
{
BOOL bFlag=m_recordset->get_EOF();
return bFlag;
}
HRESULT ADOrecordset::Prev()
{
HRESULT hr=m_recordset->MovePrevious();
return hr;
}
HRESULT ADOrecordset::Last()
{
HRESULT hr=m_recordset->MoveLast();
return hr;
}
HRESULT ADOrecordset::Next()
{
HRESULT hr=m_recordset->MoveNext();
return hr;
}
HRESULT ADOrecordset::First()
{
HRESULT hr=m_recordset->MoveFirst();
return hr;
}
HRESULT ADOrecordset::CloseRecordset(void)
{
HRESULT hr=m_recordset->Close();
return hr;
}
写完这个类之后,以后在程序中就可以直接使用这个类来对ADO进行访问,写一个简单的测试代码:
假定我已在ODBC中新建一数据源:DSN=Test,Username=chenbin,Password=caiyao,那么如果想用ADO对该数据源进行访问的话,就可以用下面的代码:
void __fastcall TForm1::Button1Click(TObject *Sender)
{
ADOConnection m_Connection;
ADOrecordset rst;
if(m_Connection.Open(L"Test",L"chenbin",L"caiyao"))
{
if(rst.SetConnect(m_Connection.m_pConnection))
{
if(rst.Open("select * from family"))
{
if(rst.First()==S_OK)
{
while(!rst.get_EOF())
{
Memo1->Lines->Add(rst.GetFieldValue("name").AsString());
rst.Next();
}
}
}
}
}
}