在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(); } } } } } }

|