參考FROM:http://hi.baidu.com/sunkanghome/item/e1fda510b3186359f1090ee2sql
在使用這三個對象的時候,須要定義與之相對應的智能指針:_ConnectionPtr、_CommandPtr、_RecordsetPtr數據庫
使用智能指針要:定義指針變量、建立其實例(實例化)、調用方法和屬性。該智能指針在析構對象時,自動調用Release方法,即便用後不須要手動釋放內存,代碼更加簡潔。編程
但須要調用Close方法,關閉鏈接Connection或者記錄集RecordSet。安全
在工程的stdafx.h中加入以下語句:服務器
#import "c:\\Program Files\\Common Files\\System\\ADO\\msado15.dll" rename_namespace("ADOCG") rename("EOF","adoEOF") //rename("BOF","adoBOF") no_namespace using namespace ADOCG;
注:import代碼要在一行中完成,換行需添加'\'ide
在基於MFC的應用裏,在應用類的InitInstance成員函數中初始化OLE/COM庫環境,直接使用AfxOleInit,在退出應用時,該函數自動負責COM資源的釋放,比較方便,不用在函數
ExitInitInstance中添加相關操做:優化
BOOL CYourApp::InitInstance() { AfxEnableControlContainer(); //初始化OLE DLLs if(!AfxOleInit()) { AfxMessageBox("初始化OLE DLL失敗!"); Return FALSE; } ...... }
_ConnectionPtr m_pConnection;
在App類的cpp文件InitInstance方法中:ui
m_pConnection.CreateInstance("ADODB.Connection"); //或者m_pConnection.CreateInstance(__uuidof(Connection));
使用'.'而不是->建立m_Connection實例,而後m_pConnection->open方法建立鏈接。spa
2.3.1 使用JET數據庫引擎實現對Acess2000類型的數據庫info.mdb的鏈接
CString strSQL=_T("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=info.mdb;User ID=admin;Passward=;");
2.3.2 使用OLE DB提供者實現對SQL Server的標準安全鏈接串
CString str SQL=_T("Provider=SQLOLEDB;Data Source=local;Initial Catalog=DVDRentDB_Data.MDF;User ID=sa;Password=123456;");
或者是在此處不設置User ID和Password,而直接在Open的第二、3個參數中設置。
CString strConnection="Provider=SQLOLEDB;DataSource=local;Initial Catalog=DVDRentDB_Data.MDF"; m_pConnection->Open((_bstr_t)strSQL,"sa","820415",adModeUnknown);
注意:
2.3.3 使用OLE DB提供者實現對遠程SQL Server的標準安全鏈接串
strConnect=_T("Provider=sqloledb;Network Library=DBMSSOCN;" "Data Source=130.120.110.001,1433;" "Initial Catalog=MyDateBaseName;" "User ID=MyUserName;Password=MyPassword;");
在ADO的操做中建議使用try...catch( )來捕獲錯誤信息,由於它有時會常常出現一些意想不到的錯誤
try { m_pConnection->Open( (_bstr_t) strSQL," "," ",adModeUnknown); } catch(_com_error e) //捕捉異常 { CString strError; strError.Format( "鏈接數據庫發生異常! \r \n錯誤信息:%s",e.ErrorMessage( ) ); AfxMessageBox(errormessage); //顯示錯誤信息 }
綜上:InitInstance方法中可:
if(!AfxOleInit()) { AfxMessageBox("初始化OLE DLL失敗!"); Return FALSE; } m_pConnection.CreateInstance("ADODB.Connection"); //或者m_pConnection.CreateInstance(__uuidof(Connection)); try { m_pConnection->ConnectionTimeout = 3; //鏈接ACCESS2000 m_pConnection->Open("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=d:/Attendence/AttendenceDB.mdb","","",adModeUnknown); } catch(_com_error e) { AfxMessageBox(e.Description() + _T("\n數據庫鏈接失敗")); }
通常重載App類的ExitInstace( )函數,調用m_pConnection的Close方法關閉鏈接便可:
m_pConnection->Close( );
m_pConnection=NULL;
注意:因爲初始化COM庫調用的是AfxOleInit,這種方法初始化COM庫的優勢就在於資源的釋放也是自動進行的,因此沒必要擔憂資源泄漏的問題。
_CommandPtr接口
該接口返回一個記錄集, 在使用_CommandPtr接口時,能夠利用全局_ConnectionPtr接口,也能夠在_CommandPtr接口裏直接使用鏈接串。若是隻執行一次或者幾回數據庫訪問操做,後者是比較好的選擇。可是,若是頻繁訪問數據庫,並要返回不少記錄集,那麼應該使用全局_ConnectionPtr接口建立一個數據庫鏈接,而後使用_CommandPtr接口執行存儲過程和SQL語句。
_RecordsetPtr接口
該接口是一個記錄集對象, 與前兩種對象相比,它對記錄集提供了更多的控制功能,如記錄鎖定、遊標控制等。
假定已經使用鏈接指針m_pConnection對象建立了數據源的鏈接:
_RecordsetPtr m_pRecordset; //聲明記錄集指針 m_pRecordset.CreateInstance(__uuidof(Recordset)); //建立實例
記錄集指針建立完畢後,調用該指針的Open方法打開記錄集。
//讀取數據庫: CString sqlHasRecord; sqlHasRecord.Format("SELECT * FROM WorkUser WHERE MemberID = '%s'" , m_StringNumber); HRESULT hr = m_pRecordset->Open(
sqlHasRecord.GetBuffer(0),
_variant_t((IDispatch*)theApp.m_pConnection, true),
adOpenDynamic,
adLockPessimistic,
adCmdText
);
Open函數聲明以下:
HRESULT Recordset15::Open ( const _variant_t & Source, //sql語句、表名、command對象 const _variant_t & ActiveConnection, //已經創建好的鏈接 enum CursorTypeEnum CursorType, //用於設置在打開Recordset時提供者應使用的遊標類型,默認值adOpenForwardOnly enum LockTypeEnum LockType, //用於設置在打開Recordset時提供者應使用的鎖定類型,默認值adLockReadOnly long Options ) ; //獲取Source(即Open第一個參數)的方式
若是第一個參數是sql語句則選擇adCmdText
若是第一個參數是表名則選擇adCmdTable
//讀取數據庫: CString sqlHasRecord; sqlHasRecord.Format("SELECT * FROM WorkUser WHERE MemberID = '%s'" , m_StringNumber); HRESULT hr = m_pRecordset->Open(sqlHasRecord.GetBuffer(0), _variant_t((IDispatch*)theApp.m_pConnection, true), adOpenDynamic, adLockPessimistic, adCmdText); if (SUCCEEDED(hr)) { while (!m_pRecordset->adoEOF || !m_pRecordset->BOF)//遍歷返回的每一條記錄 { CString m_StringID; m_StringID = (LPCSTR)_bstr_t(m_pRecordset->GetCollect("FeatureID"));//讀取id
m_pRecordset->MoveNext();
} } m_pRecordset->Close(); //記錄用完以後須要關閉
通常在返回記錄集時,一般要遍歷結果記錄集,以便查看或編輯某一條記錄:
注:爲了不發生異常:
MoveFirst、MovePrev以前,須要使用記錄集的指針BOF屬性來檢測當前的記錄集指針 是否位於第一條記錄以前;
MoveLast、MoveNext以前須要使用記錄集指針的EOF屬性來檢測當前的記錄集指針 是否位於最後一條記錄以後.
記錄集定位
兩種定位方法:前者經過設置或者獲取AbsolutePosition屬性,其值從1開始,而且當前記錄爲記錄集中第一條記錄時等於1, 後者經過設置或獲取BookMark屬性.
讀取字段值:
m_pRecordset->GetCollect (字段名); // 字符串 -> 字段名 or 整型(long) -> 字段對應的序號
設置字段值:
m_pRecordset->PutCollect (字段名,新值);
//兩個方法的原型: _variant_t GetCollect ( const _variant_t & Index ) void PutCollect ( const _variant_t & Index , const _variant_t &pvar )
添加新的記錄:AddNew
編輯當前記錄:Edit
刪除當前記錄:Delete
AddNew方法:直接在表的末尾續加新記錄,該方法可使用參數,在參數中指定要添加的新紀錄;
也能夠不使用參數,而在後面使用PutCollect方法,並需使用Update函數保存新紀錄。
Update方法:用於保存從調用AddNew方法以來所做的任何更改。
//在表的末尾增長新紀錄 m_pRecordset->AddNew(); //------------------ m_pRecordset->PutCollect("姓名",_variant_t(m_strName)); m_pRecordset->PutCollect("工做單位",_variant_t(m_strComName)); m_pRecordset->PutCollect("單位地址",_variant_t(m_strComAddr)); //------------------ m_pRecordset->Update();//更新數據庫-將新紀錄存入數據庫
在對記錄集的操做完成後,必須及時關閉記錄集。
if ( m_pRecordset != NULL ) { m_pRecordset ->Close( ); m_pRecordset =NULL; }
1.編輯SQL語句
2.執行connection對象的Excute()方法
//_ConnectionPt m_pConnection 智能指針對象
strSql.Format(_T("UPDATE WorkUser SET MemberName = '%s', MemberPosition = '%s' WHERE MemberID = '%s' "),m_StringName, m_StringPosition, m_StringNumber); try { m_pConnection->Execute(_bstr_t(strSql), 0, adCmdText); } catch(_com_error e) { MessageBox(e.Description()); return; }
注:_variant_t和_bstr_t這兩個類分別封裝並管理VARIANT和BSTR這兩種數據類型,VARIANT和BSTR這兩種類型是COM中使用的數據類型。
4.1 初始化引入相關的庫+Connection對象的建立和數據庫的鏈接
#import "c:\\Program Files\\Common Files\\System\\ADO\\msado15.dll" rename_namespace("ADOCG") rename("EOF","adoEOF") //rename("BOF","adoBOF") using namespace ADOCG;
//... ... _ConnectionPtr m_pConnection;
//... ... if(!AfxOleInit()) { AfxMessageBox("初始化OLE DLL失敗!"); Return FALSE; } m_pConnection.CreateInstance("ADODB.Connection"); try { m_pConnection->ConnectionTimeout = 3; //鏈接ACCESS2000 m_pConnection->Open("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=d:/Attendence/AttendenceDB.mdb","","",adModeUnknown); } catch(_com_error e) { AfxMessageBox(e.Description() + _T("\n數據庫鏈接失敗")); }
4.2 Recordset對象的聲明與建立實例:
_RecordsetPtr m_pRecordset;
m_pRecordset.CreateInstance(__uuidof(Recordset)); //建立實例
4.3 讀取記錄內容:
CString sqlHasRecord; sqlHasRecord.Format("SELECT * FROM WorkUser WHERE MemberID = '%s'" , m_StringNumber); HRESULT hr = m_pRecordset->Open(sqlHasRecord.GetBuffer(0), _variant_t((IDispatch*)theApp.m_pConnection, true), adOpenDynamic, adLockPessimistic, adCmdText); if (SUCCEEDED(hr)) { while (!m_pRecordset->adoEOF || !m_pRecordset->BOF)//遍歷返回的每一條記錄 { CString m_StringID; m_StringID = (LPCSTR)_bstr_t(m_pRecordset->GetCollect("FeatureID"));//讀取id m_pRecordset->MoveNext(); } } m_pRecordset->Close(); //記錄用完以後須要關閉
4.4 插入新記錄:
CString strSql; strSql.Format("INSERT INTO WorkUser(MemberName, MemberID, MemberPosition, FeatureID, BeDeleted, SendedToClient) VALUES('%s', '%s', '%s', %d, 0, 0)",「ZhangSan」,」14S051000」, 「Student」, 16); try { (theApp.m_pConnection)->Execute(_bstr_t(strSql), 0, adCmdText); } catch(_com_error e) { MessageBox(e.Description()); return; }
4.5 更新記錄:
strSql.Format(_T("UPDATE WorkUser SET MemberName = '%s', MemberPosition = '%s' WHERE MemberID = '%s' "),m_StringName, m_StringPosition, m_StringNumber); try { (theApp.m_pConnection)->Execute(_bstr_t(strSql), 0, adCmdText); } catch(_com_error e) { MessageBox(e.Description()); return; }
4.6 刪除記錄:
CString strSql; strSql.Format(_T("DELETE FROM WorkUser WHERE FeatureID = %s "), FeatureID[i]); try { (theApp.m_pConnection)->Execute(_bstr_t(strSql), 0, adCmdText); } catch(_com_error e) { MessageBox(e.Description()); return FALSE; }
4.7 讀取字節流文件:
讀取圖像數據:
try { CString sql; sql.Format("select * from WorkUser where MemberID='%s'",MemberID); HRESULT hr = m_pRecordset->Open(sql.GetBuffer(0),_variant_t((IDispatch *)theApp.m_pConnection,true),adOpenDynamic,adLockPessimistic,adCmdText); if(SUCCEEDED(hr)) { if(m_pRecordset->adoEOF||m_pRecordset->BOF) { MessageBox(_T("數據庫中沒有相應的記錄")); return; } else { long lDataSize = m_pRecordset->GetFields()->GetItem(imgColName.GetBuffer(0))->ActualSize; if (lDataSize>0) { _variant_t varBLOB; varBLOB = m_pRecordset->GetFields()->GetItem(imgColName.GetBuffer(0))->GetChunk(lDataSize); if(varBLOB.vt == (VT_ARRAY | VT_UI1)) { if(buffer) ///從新分配必要的存儲空間 { char *pBuf = NULL; SafeArrayAccessData(varBLOB.parray,(void **)&pBuf); memcpy(buffer,pBuf,lDataSize); ///複製數據到緩衝區buffer SafeArrayUnaccessData (varBLOB.parray); } } } else { MessageBox(_T("數據庫中的圖像數據爲空!")); return; } } } } catch (...) { MessageBox(_T("數據庫訪問出錯")); } m_pRecordset->Close();
4.8 保存字節流文件:
CString sql; sql.Format("select * from WorkUser where MemberID='%s'",MemberID); HRESULT hr = m_pRecordset->Open(sql.GetBuffer(0),_variant_t((IDispatch *)theApp.m_pConnection,true),adOpenDynamic,adLockPessimistic,adCmdText); if(SUCCEEDED(hr)) { if (!m_pRecordset->adoEOF||!m_pRecordset->BOF) { char *pBuf = buffer; VARIANT varBLOB; SAFEARRAY *psa; SAFEARRAYBOUND rgsabound[1]; if(pBuf) { rgsabound[0].lLbound = 0; rgsabound[0].cElements = bufLength; psa = SafeArrayCreate(VT_UI1, 1, rgsabound); //分配的數據類型爲unsigned int (1 byte 長度的類型) for (long i = 0; i < (long)bufLength; i++) SafeArrayPutElement (psa, &i, pBuf++); varBLOB.vt = VT_ARRAY | VT_UI1; varBLOB.parray = psa; m_pRecordset->GetFields()->GetItem(imgColName.GetBuffer(0))->AppendChunk(varBLOB); } m_pRecordset->Update(); } else { MessageBox(_T("數據庫中沒有相應用戶的記錄!")); return; } } m_pRecordset->Close();
SafeArrayDestroy