首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> VC >> 關於VC++

ADO 封裝類資料庫程式開發實戰(第二版)下集:CAdoRecordSet 核心方法詳解

     編輯:關於VC++

前言

承接上集內容,本文將深入剖析 CAdoRecordSet 類的核心方法與屬性,涵蓋記錄集操作、欄位存取、游標控制、批次更新、書籤導航、Blob 處理等進階主題。所有程式碼片段均取自實際專案,經過重構與註解優化,適合直接套用至生產環境。

一、建構子與連線綁定

CAdoRecordSet::CAdoRecordSet();
CAdoRecordSet::CAdoRecordSet(CAdoConnection *pConnection);
void CAdoRecordSet::SetAdoConnection(CAdoConnection *pConnection);

建構子支援預設建構與帶連線指標建構兩種模式。SetAdoConnection 用於在記錄集建立後動態綁定 CAdoConnection 實例,實現連線物件的複用與解耦。

二、Open 方法:多樣化的資料來源開啟策略

BOOL CAdoRecordSet::Open(LPCTSTR strSQL, long lOption,
                         CursorTypeEnum CursorType, LockTypeEnum LockType);
參數說明
strSQLSQL 指令、資料表名、預存程序或持久化 Recordset 檔案路徑
lOption指定 strSQL 類型:adCmdText(預設)、adCmdTable、adCmdStoredProc、adCmdFile、adAsyncExecute 等
CursorType游標類型:adOpenForwardOnly、adOpenKeyset、adOpenDynamic、adOpenStatic
LockType鎖定模式:adLockReadOnly、adLockPessimistic、adLockOptimistic、adLockBatchOptimistic

實戰範例:

if (m_adoConnection.OpenUDLFile(_T("C:\\mm.udl"))) {
    m_adoRecordSet.SetAdoConnection(&m_adoConnection);
    m_adoRecordSet.SetCursorLocation(adUseClient); // 客戶端游標支援斷線操作
    m_adoRecordSet.Open(_T("ado"), adCmdTable);    // 直接開啟資料表
    
    // 交易式新增資料
    m_adoConnection.BeginTrans();
    bool bSex = (m_strSex == _T("男"));
    m_adoRecordSet.AddNew();
    bool bOk = m_adoRecordSet.PutCollect(_T("age"), m_nAge)
            && m_adoRecordSet.PutCollect(_T("length"), m_fLength)
            && m_adoRecordSet.PutCollect(_T("name"), m_strName)
            && m_adoRecordSet.PutCollect(_T("tel"), m_strTel)
            && m_adoRecordSet.PutCollect(_T("money"), m_cyMoney)
            && m_adoRecordSet.PutCollect(_T("date"), m_dtDate)
            && m_adoRecordSet.PutCollect(_T("sex"), bSex);
    
    if (!bOk) {
        m_adoRecordSet.CancelUpdate();
        m_adoConnection.RollbackTrans();
    } else {
        m_adoRecordSet.Update();
        m_adoConnection.CommitTrans();
    }
    // 清理編輯狀態
    if (m_adoRecordSet.GetEditMode() != adEditNone)
        m_adoRecordSet.CancelUpdate();
    m_adoRecordSet.Close();
}

三、資料異動核心方法群

1. AddNew / Update / CancelUpdate

  • AddNew():啟動新增模式,游標移至暫存緩衝區
  • Update():提交新增或修改至資料來源
  • CancelUpdate():放棄尚未 Update 的變更,游標回到原記錄

2. 批次更新:UpdateBatch / CancelBatch

BOOL UpdateBatch(AffectEnum AffectRecords = adAffectAll);
BOOL CancelBatch(AffectEnum AffectRecords = adAffectAll);

僅支援 Keyset 或 Static 游標。AffectRecords 可控制影響範圍:adAffectCurrent、adAffectGroup、adAffectAll、adAffectAllChapters。

3. 刪除記錄

BOOL Delete(AffectEnum AffectRecords = adAffectCurrent);

同樣支援多種影響範圍常數,搭配 Filter 屬性可實現條件式批次刪除。

四、欄位存取:PutCollect / GetCollect 多型重載

封裝類提供豐富的重載,支援索引與欄位名兩種存取方式,並自動處理 _variant_t、CString、數值型別、COleDateTime、COleCurrency 等轉換:

BOOL PutCollect(LPCTSTR strFieldName, const CString &value);
BOOL PutCollect(LPCTSTR strFieldName, const COleDateTime &value);
BOOL GetCollect(LPCTSTR strFieldName, CString &strValue);
BOOL GetCollect(LPCTSTR strFieldName, COleDateTime &value);
// ... 其餘數值型別重載略

特色:若資料庫欄位為數字字串,可直接以 long 或 double 讀取,封裝層自動完成型別轉換。

五、記錄集同步與持久化

Requery vs Resync

方法行為適用場景
Requery重新執行原始查詢,等同 Close+Open需看見新增記錄、結構變更
Resync僅同步現有記錄與資料庫最新值靜態/唯向前游標,效能較佳

Resync 不會重新執行命令,因此無法看見他人新增的記錄;若 CursorLocation=adUseClient,僅非唯讀 Recordset 可用。

Save / Load 離線儲存

BOOL Save(LPCTSTR strFileName, PersistFormatEnum PersistFormat = adPersistXML);
BOOL Load(LPCTSTR strFileName);

支援 adPersistADTG (二進位) 與 adPersistXML (預設) 兩種格式。Filter 生效時僅儲存篩選後的列。

六、導航與定位方法

  • MoveFirst/Last/Next/Previous:基本游標移動
  • Move(lRecords, Start):相對移動,Start 可為 adBookmarkCurrent/First/Last
  • Find/FindFirst:條件查找,支援 SearchDirectionEnum
  • SetFilter/GetFilter:動態篩選,如 Name <> 'anyou' And Age > 20
  • SetSort:排序,如 Name DESC, Age ASC

七、書籤與 Clone 技術

void GetBookmark();          // 取得目前記錄書籤
BOOL SetBookmark();          // 移動至書籤記錄
BOOL Clone(CAdoRecordSet &pRecordSet); // 建立複本,獨立游標

Clone 後的 Recordset 關閉互不影響,適合多視圖同步顯示同一資料集。

八、Blob/長資料處理:AppendChunk / GetChunk

BOOL AppendChunk(LPCTSTR strFieldName, LPCTSTR lpszFileName); // 直接寫入檔案
BOOL GetChunk(LPCTSTR strFieldName, CBitmap &bitmap);         // 讀取圖片

寫入範例:

m_adoRecordSet.AddNew();
m_adoRecordSet.SetFieldValue(_T("ID"), 5);
m_adoRecordSet.AppendChunk(_T("Document"), _T("C:\\doc1.txt"));
m_adoRecordSet.Update();

讀取範例:

long size = GetFieldActualSize(strFieldName);
if ((adFldLong & GetFieldAttributes(strFieldName)) && size > 0) {
    BYTE *lpData = new BYTE[size];
    if (GetChunk(GetField(strFieldName), (LPVOID)lpData)) {
        // 處理二進位資料
    }
    delete[] lpData;
}

九、欄位中繼資料查詢

方法用途
GetFieldName / GetFields / GetField取得欄位名稱、集合、單一欄位物件
GetFieldAttributes欄位屬性:adFldUpdatable、adFldIsNullable、adFldLong 等
GetFieldDefineSize / GetFieldActualSize定義長度 vs 實際長度
GetFieldType資料型別:adVarChar、adInteger、adDate、adLongVarBinary 等
IsFieldNull快速判斷 Null 值

十、狀態與資訊屬性

  • GetState():adStateOpen、adStateExecuting、adStateFetching 等位元組合
  • GetStatus():批次更新狀態,adRecOK、adRecNew、adRecModified、adRecDeleted 等
  • GetRecordCount()、GetFieldsCount()、IsBOF()、IsEOF()
  • GetEditMode():adEditNone、adEditInProgress、adEditAdd、adEditDelete

十一、DataGrid 控制項繫結實戰

if (m_adoConnection.ConnectAccess(_T("database.mdb"))) {
    m_adoRecordSet.SetAdoConnection(&m_adoConnection);
    m_adoRecordSet.SetCursorLocation(adUseClient); // 必須為客戶端游標
    if (m_adoRecordSet.Open(lpszPathName, adCmdTable)) {
        m_wndDataGrid.SetRefDataSource(NULL);
        m_wndDataGrid.SetRefDataSource((LPUNKNOWN)m_adoRecordSet.GetRecordset());
        m_wndDataGrid.SetAllowAddNew(TRUE);
        m_wndDataGrid.SetAllowDelete(TRUE);
        m_wndDataGrid.SetAllowUpdate(TRUE);
        m_wndDataGrid.Refresh();
    }
}

關鍵點:必須設定 adUseClient,否則 DataGrid 無法正確繫結。

十二、Supports 方法:功能偵測

BOOL Supports(CursorOptionEnum CursorOptions);

常用檢查項:adAddNew、adDelete、adUpdate、adBookmark、adMovePrevious、adUpdateBatch、adSeek。注意:回傳 True 僅代表提供者支援該功能,不保證所有情境下皆可用(如多表 Join 的更新限制)。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved