ado2007.h文件源码清单
#pragma once #include <oledberr.h> #import "C:/Program Files/Common Files/System/ado/msadox.dll" rename_namespace("ADOX") / rename("_Collection", "_CollectionX")/ rename("_DynaCollection", "_DynaCollectionX")/ rename("DataTypeEnum", "DataTypeEnumX")/ rename("Properties", "PropertiesX")/ rename("Property", "PropertyX") #import "C:/Program Files/Common Files/System/ado/msado15.dll"/ no_namespace/ rename( "EOF", "adoEOF" ) #include <string> #include <list> #include <map> #include <assert.h> /* 组成文件:ado2007.h ado2007.cpp 主要功能:通过ADO对Access2007数据库操作提供最基本的支持 程序设计:Kagula 起始日期:2010/07/01 外部接口修改次数: 内部代码修改次数: 最后更新日期: 测试环境:[1]VisualStudio 2008 + SP1 [2]Access2007中文版(用于建立accdb文件) 测试代码:使用了MFC的一个Dialog类实例做了连接,取记录,修改记录测试。 备注:[1]在Access2007里ID字段和数字类型字段默认为adInteger 文本类型默认为adVarWChar 这里只假设有以上两种字段类型。 [2]CADO2007的实例,可能线程不安全。 */ struct CADOEle { CADOEle() { wsValue = L""; nValue = 0; } CADOEle(const CADOEle &s) { this->wsValue = s.wsValue; this->nValue = s.nValue; } std::wstring wsValue; int nValue; }; class CADO2007 { public: CADO2007(void); ~CADO2007(void); bool Conn(std::wstring wsCS,std::wstring UserId,std::wstring pwd); //若已经连接则和DB重新建立连接 std::list<std::map<std::wstring,CADOEle>> / Query(std::wstring wsSql); //执行SQL语句并返回结果记录集 bool Exec(std::wstring wsSql); //执行SQL语句并返回是否成功标志 bool isConn() //测试是否连接 { if(pConnection==NULL) return false; if(pConnection->State!=adStateOpen) return false; return true; } protected: std::wstring wsCnn; std::wstring wsUserID; std::wstring wsPassword; _ConnectionPtr pConnection; _RecordsetPtr pRst; CursorTypeEnum CursorType; LockTypeEnum LockType; private: void PrintProviderError(_ConnectionPtr pConnection); void PrintComError(_com_error &e); void TESTHR(HRESULT x) { if FAILED(x) _com_issue_error(x); } void ASSERT_CNN() { assert(pConnection!=NULL); if(pConnection->State!=adStateOpen) assert(NULL); } };
ado2007.cpp文件源码清单
#include "ADO2007.h" #include "Utils.h" CADO2007::CADO2007(void) { if(FAILED(::CoInitialize(NULL))) { throw std::wstring(L"[CADO2007]初始化COM接口失败!"); } pConnection=NULL; pRst=NULL; wsCnn =L""; wsUserID =L""; wsPassword=L""; /* 记录集游标(CursorType)决定了你可以对一个记录集进行什么样的操作, 并决定了其他用户可以对记录集可以进行怎么样的改变。值:0-3 0:默认值,movenext方法单向向后移动游标,游标指向哪行 就能处理哪行(顺序访问) 1:键盘指针,可以即向前 又向后移动游标,当用户对数据进行修改后, 其他用户可以立即看到你的修改,但看不到其他用户添加/删除的记录 2:可以进行任何类型的移动,并可以看到其他用户的添加/修改/删除操作 3:可以任意移动,但所作的修改不会再其他客户端立即显示出来 */ CursorType = adOpenDynamic; /* 锁定类型(LockType) 锁定类型决定了当不止一个用户同时试图改变一个记录时,数据库应该如何操作。 1:默认值,只读属性,只能读 不能修改 2:只能被一个用户修改,修改时数据库被锁定(最安全) 3:最优化锁定,可以同时被多个用户修改,直到update更新数据库时才被锁定 4:数据可以被修改且不锁定其他用户,指定数据批处理更新(不提倡) */ LockType = adLockOptimistic; } CADO2007::~CADO2007(void) { if(pRst) if(pRst->State==adStateOpen) pRst->Close(); if(pConnection) if(pConnection->State==adStateOpen) pConnection->Close(); ::CoUninitialize(); } bool CADO2007::Conn(std::wstring wsConnectString,std::wstring UserId,std::wstring pwd) { wsCnn = wsConnectString; wsUserID = UserId; wsPassword = pwd; if(pConnection) { if(pConnection->State==adStateOpen) pConnection->Close(); } _bstr_t strCnn(wsCnn.c_str()); _bstr_t UserID(wsUserID.c_str()); _bstr_t Password(wsPassword.c_str()); try { if(pConnection==NULL) TESTHR(pConnection.CreateInstance(__uuidof(Connection))); pConnection->Open(strCnn,UserID,Password,adConnectUnspecified); } catch(_com_error &e) { PrintProviderError( pConnection); PrintComError(e); return false; } return true; } std::list<std::map<std::wstring,CADOEle>> CADO2007::Query(std::wstring wsSql) { ASSERT_CNN(); std::list<std::map<std::wstring,CADOEle>> list; if(pRst) if(pRst->State==adStateOpen) pRst->Close(); _bstr_t strSQL(wsSql.c_str()); std::map<std::wstring,CADOEle> row; std::wstring wsColName; try { if(pRst==NULL) pRst.CreateInstance(__uuidof(Recordset)); pRst->Open(strSQL,_variant_t((IDispatch *)pConnection,true), CursorType,LockType,adCmdText); } catch(_com_error &e) { PrintProviderError(pConnection); PrintComError(e); goto _END2; } if( pRst==NULL || pRst->State!=adStateOpen) goto _END2; //把RecordSet中的数据放到List容器中。 if (pRst->RecordCount>0) pRst->MoveFirst(); while ( !pRst->adoEOF ) { //get col.begin try { FieldsPtr fields = pRst->GetFields(); if ( fields == NULL ) goto _END; long count = fields->GetCount(); _bstr_t collect_name; DataTypeEnum vt; //FieldAttributeEnum attribute; CADOEle ele; for ( long i = 0; i < count; i++ ) { collect_name = fields->Item[i]->GetName(); wsColName = collect_name; vt = fields->Item[i]->GetType(); //attribute = (FieldAttributeEnum)fields->Item[i]->Attributes; ele.nValue=0,ele.wsValue=L""; _variant_t v_t = fields->Item[i]->Value; if( vt==NULL || v_t.vt==VT_NULL ) { }else if (vt == adInteger) //默认ID字段的类型、数字类型 { ele.nValue = v_t; } else if ( vt == adVarWChar ) //默认文本类型 { ele.wsValue = (wchar_t *)(v_t.pbstrVal); } row[wsColName] = ele; } fields->Release(); } catch (_com_error &e) { PrintProviderError(pConnection); PrintComError(e); goto _END; } list.push_back(row); //get col.end pRst->MoveNext(); } _END: pRst->Close(); pRst = NULL; _END2: return list; } bool CADO2007::Exec(std::wstring wsSql) { ASSERT_CNN(); _CommandPtr pCmd=NULL; _bstr_t strSQL(wsSql.c_str()); kagula::OutputDebugString(L"[CADO2007::Exec][%s]/n",wsSql.c_str()); try{ TESTHR(pCmd.CreateInstance(__uuidof(Command))); pCmd->ActiveConnection=pConnection; pCmd->CommandText=strSQL; pCmd->Execute(NULL,NULL,adCmdText); } catch(_com_error &e) { PrintProviderError(pConnection); PrintComError(e); return false; } return true; } void CADO2007::PrintComError(_com_error &e) { _bstr_t bstrSource(e.Source()); _bstr_t bstrDescription(e.Description()); long nCode=e.Error(); //Print Com errors; kagula::OutputDebugString(L"Error=ADO/n"); kagula::OutputDebugString(L"/tCode=%08lx/n",nCode); kagula::TRACE("/tCode meaning=%s/n",e.ErrorMessage()); kagula::TRACE("/tSource=%s/n",(LPCSTR)bstrSource); kagula::TRACE("/tDescription=%s/n",(LPCSTR)bstrDescription); } void CADO2007::PrintProviderError(_ConnectionPtr pConnection) { ErrorPtr pErr=NULL; if( (pConnection->Errors->Count) > 0) { long nCount=pConnection->Errors->Count; for(long i=0;i<nCount;i++) { pErr=pConnection->Errors->GetItem(i); kagula::TRACE("/t Error number:%x/t%s",pErr->Number, (LPCSTR)pErr->Description); } } }