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

ADO 直操 Access 實戰全攻略:從 #import 到 CRUD、Command、預存程序完整範例

     編輯:關於VC++

專案展示

AdoRWAccess 運行畫面

資料庫:Demo.mdb,資料表:DemoTable,欄位:Name (Text)、Age (Integer)。

環境建置三步驟

// 1. Stdafx.h 引入類型庫
#import "c:\\program files\\common files\\system\\ado\\msado15.dll" \
    no_namespace rename("EOF", "adoEOF")

// 2. COM 初始化 (擇一)
// 方案 A: MFC 自動管理
AfxOleInit(); // 僅呼叫一次,自動在結束時 CoUninitialize

// 方案 B: 手動控制
CoInitialize(NULL); // 初始
// ... 程式結束 ...
CoUninitialize();   // 釋放

// 3. 編譯產生 .tlh/.tli,智慧指標自動管理參考計數

三大智慧指標速查

指標用途關鍵方法
_ConnectionPtr連線管理Open, Close, Execute, BeginTrans, CommitTrans, RollbackTrans, OpenSchema
_RecordsetPtr資料游標Open, Close, MoveFirst/Next/Previous/Last, AddNew, Update, Delete, GetCollect, PutCollect, GetFields, Fields, adoEOF, BOF
_CommandPtr參數化指令/預存程序ActiveConnection, CommandText, Execute, Parameters, CreateParameter

_ConnectionPtr 連線操作

_ConnectionPtr m_pConnection;
AfxOleInit();
m_pConnection.CreateInstance(__uuidof(Connection));

try {
    m_pConnection->Open(_T("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=Demo.mdb"),
                        _T(""), _T(""), adModeUnknown);
} catch (_com_error e) {
    AfxMessageBox(_T("連線失敗,確認 Demo.mdb 是否在當前路徑!"));
    return FALSE;
}

// 關閉
if (m_pConnection->State) m_pConnection->Close();
m_pConnection = NULL;

_RecordsetPtr 開啟資料表

_RecordsetPtr m_pRecordset;
m_pRecordset.CreateInstance(__uuidof(Recordset));

try {
    m_pRecordset->Open(_T("SELECT * FROM DemoTable"),
        theApp.m_pConnection.GetInterfacePtr(), // 取得 IDispatch*
        adOpenDynamic, adLockOptimistic, adCmdText);
} catch (_com_error* e) {
    AfxMessageBox(e->ErrorMessage());
}

讀取資料並顯示於 ListBox

_variant_t var; CString strName, strAge;
try {
    if (!m_pRecordset->BOF) m_pRecordset->MoveFirst();
    else { AfxMessageBox(_T("表內無資料")); return; }
    
    while (!m_pRecordset->adoEOF) {
        var = m_pRecordset->GetCollect(_T("Name"));
        if (var.vt != VT_NULL) strName = (LPCSTR)_bstr_t(var);
        
        var = m_pRecordset->GetCollect(_T("Age"));
        if (var.vt != VT_NULL) strAge = (LPCSTR)_bstr_t(var);
        
        m_AccessList.AddString(strName + _T(" --> ") + strAge);
        m_pRecordset->MoveNext();
    }
    m_AccessList.SetCurSel(0);
} catch (_com_error* e) { AfxMessageBox(e->ErrorMessage()); }

新增記錄

try {
    m_pRecordset->AddNew();
    m_pRecordset->PutCollect(_T("Name"), _variant_t(m_Name));
    m_pRecordset->PutCollect(_T("Age"), _variant_t(_ttoi(m_Age)));
    m_pRecordset->Update();
    AfxMessageBox(_T("新增成功!"));
} catch (_com_error* e) { AfxMessageBox(e->ErrorMessage()); }

游標移動與定位

// 相對移動
m_pRecordset->MoveFirst();
m_pRecordset->Move(long(curSel)); // curSel 為 ListBox 選取索引 (0-based)

// 絕對定位 (需支援書籤的游標)
m_pRecordset->MoveFirst();
m_pRecordset->Move(3, adBookmarkFirst); // 從第一筆起跳 3 筆

修改記錄

try {
    m_pRecordset->MoveFirst(); m_pRecordset->Move(1); // 定位第 2 筆 (0-based)
    m_pRecordset->PutCollect(_T("Name"), _variant_t(m_Name));
    m_pRecordset->PutCollect(_T("Age"), _variant_t(_ttoi(m_Age)));
    m_pRecordset->Update();
} catch (_com_error* e) { AfxMessageBox(e->ErrorMessage()); }

刪除記錄

try {
    m_pRecordset->MoveFirst(); m_pRecordset->Move(1);
    m_pRecordset->Delete(adAffectCurrent); // 僅刪除目前記錄
    m_pRecordset->Update();
} catch (_com_error* e) { AfxMessageBox(e->ErrorMessage()); }

關閉記錄集

m_pRecordset->Close(); m_pRecordset = NULL;

_CommandPtr 執行 SQL 與預存程序

// 執行 SQL
_CommandPtr m_pCommand;
m_pCommand.CreateInstance(__uuidof(Command));
m_pCommand->ActiveConnection = m_pConnection;
m_pCommand->CommandText = _T("SELECT * FROM DemoTable");
m_pRecordset = m_pCommand->Execute(NULL, NULL, adCmdText);

// 執行預存程序 (Access 稱 Query)
m_pCommand->CommandText = _T("DemoQuery");
m_pCommand->Execute(NULL, NULL, adCmdStoredProc);

// 參數化查詢範例 (需 _ParameterPtr)
_ParameterPtr pParam = m_pCommand->CreateParameter(_T("@Age"), adInteger, adParamInput, 4, 25);
m_pCommand->Parameters->Append(pParam);
m_pCommand->CommandText = _T("SELECT * FROM DemoTable WHERE Age > @Age");
m_pRecordset = m_pCommand->Execute(NULL, NULL, adCmdText);

錯誤處理最佳實務

  • **所有 ADO 操作包裹在 try-catch(_com_error*)** 中
  • 連線錯誤可透過 m_pConnection->Errors 集合取得詳細資訊
  • 釋放資源遵循 **逆序**:Recordset → Command → Connection
  • 智慧指標離開作用域自動 Release(),但明確設為 NULL 更安全
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved