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

VC++ ADO 數據庫編程完整指南:從連接到異常處理的最佳實踐

     編輯:VC++

基於 #import 導入類型庫的智能指針方式,拒絕繁瑣 COM 手動管理

1. 環境配置:導入 ADO 類型庫


// stdafx.h 末尾添加
#import "C:\\Program Files\\Common Files\\System\\ado\\msado15.dll" \
    no_namespace \
    rename("EOF", "adoEOF") \
    rename("BOF", "adoBOF")
  • no_namespace:直接使用 _ConnectionPtr 等類型,否則需 ADODB::_ConnectionPtr。
  • rename:避免 EOF/BOF 與 C++ 標準庫/其他庫衝突。
  • 編譯後生成 .tlh/.tli(類型庫頭文件/實現),IntelliSense 可直接識別 ADO 類。

2. COM 庫初始化(進程級,一次即可)


// 應用程序 InitInstance / main 入口
::CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); // 或 AfxOleInit()
// 退出前
::CoUninitialize();

3. 三大核心智能指針對象

4. 連接字符串大全


// Access 2000/2003 (.mdb)
Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\\Data\\db.mdb;User ID=admin;Password=secret;

// Access 2007+ (.accdb)
Provider=Microsoft.ACE.OLEDB.12.0;Data Source=C:\\Data\\db.accdb;Persist Security Info=False;

// SQL Server (OLE DB)
Provider=SQLOLEDB;Data Source=192.168.1.100;Initial Catalog=MyDB;User ID=sa;Password=123;

// SQL Server (ODBC) - 需系統 DSN
Provider=MSDASQL;DSN=MyDSN;UID=sa;PWD=123;

// Oracle
Provider=MSDAORA;Data Source=ORCL;User ID=scott;Password=tiger;

5. 完整 CRUD 範例(帶結構化異常處理)


#include 
#include  // _com_error

void DemoADO() {
    HRESULT hr;
    _ConnectionPtr pConn;
    _RecordsetPtr pRs;

    try {
        // 1. 創建連接
        hr = pConn.CreateInstance(__uuidof(Connection));
        if (FAILED(hr)) throw _com_error(hr);

        // 2. 打開連接
        _bstr_t connStr = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=test.mdb;";
        hr = pConn->Open(connStr, "", "", adModeUnknown);
        if (FAILED(hr)) throw _com_error(hr);

        // 3. 執行查詢
        _bstr_t sql = "SELECT ID, Name, Age FROM Users WHERE Age > ?";
        _CommandPtr pCmd;
        pCmd.CreateInstance(__uuidof(Command));
        pCmd->ActiveConnection = pConn;
        pCmd->CommandText = sql;
        pCmd->CommandType = adCmdText;

        // 參數化查詢(防注入)
        _ParameterPtr pParam = pCmd->CreateParameter(_T("@Age"), adInteger, adParamInput, 4, 18);
        pCmd->Parameters->Append(pParam);

        pRs = pCmd->Execute(NULL, NULL, adExecuteNoRecords);

        // 4. 遍歷結果集
        while (!pRs->adoEOF) {
            long id = pRs->GetCollect("ID");
            _bstr_t name = pRs->GetCollect("Name");
            int age = pRs->GetCollect("Age");
            printf("ID:%d Name:%s Age:%d\n", id, (LPCTSTR)name, age);
            pRs->MoveNext();
        }

        // 5. 插入示例
        sql = "INSERT INTO Users (Name, Age) VALUES (?, ?)";
        pCmd->CommandText = sql;
        pCmd->Parameters->Clear();
        pCmd->Parameters->Append(pCmd->CreateParameter(_T("@Name"), adVarWChar, adParamInput, 50, _T("張三")));
        pCmd->Parameters->Append(pCmd->CreateParameter(_T("@Age"), adInteger, adParamInput, 4, 25));
        pCmd->Execute(NULL, NULL, adExecuteNoRecords);

    } catch (_com_error &e) {
        // 統一異常處理
        _bstr_t errSrc = e.Source();
        _bstr_t errDesc = e.Description();
        printf("ADO 錯誤: 來源=%s 描述=%s 代碼=0x%08X\n", 
               (LPCTSTR)errSrc, (LPCTSTR)errDesc, e.Error());
    }

    // 6. 清理(智能指針自動 Release,但顯式關閉更佳)
    if (pRs && pRs->State) pRs->Close();
    if (pConn && pConn->State) pConn->Close();
}

6. 關鍵技術細節

  1. 變體類型 _variant_t/_bstr_t:自動管理 VARIANT/BSTR 生命週期,支持隱式轉換 (long)var, (LPCTSTR)bstr。
  2. 游標類型與鎖定:
    • adOpenForwardOnly (默認,只讀、單向、最快)
    • adOpenStatic (靜態快照、可回滾、不見他人變更)
    • adOpenDynamic (動態、實時、開銷大)
    • adLockReadOnly, adLockOptimistic, adLockPessimistic, adLockBatchOptimistic
  3. 參數化命令:CreateParameter + Parameters->Append,徹底杜絕 SQL 注入。
  4. 異常捕獲:所有 ADO 方法返回 HRESULT,失敗拋 _com_error,catch(_com_error&) 統一處理。

7. 常見錯誤與對策

類型用途創建方式
_ConnectionPtr數據源連接、事務控制CreateInstance(__uuidof(Connection)) 或 _ConnectionPtr("ADODB.Connection")
_RecordsetPtr結果集操作、游標管理CreateInstance(__uuidof(Recordset))
_CommandPtr參數化命令、存儲過程CreateInstance(__uuidof(Command))
現象原因解決
「未註冊的類」/ CLASS_E_CLASSNOTAVAILABLE未安裝 MDAC / ACE Provider安裝 Microsoft Access Database Engine (32/64 位匹配編譯目標)
「找不到安裝可用的 ISAM」Access 版本與 Provider 不匹配.mdb 用 Jet 4.0,.accdb 用 ACE 12.0
多次 Close 導致錯誤State 未檢查if (pConn->State) pConn->Close();
中文亂碼字符集不一致連接串加 ;Charset=GBK 或使用 _bstr_t 正確轉換

8. 進階主題

  • 斷開連接記錄集:pRs->ActiveConnection = NULL 後可離線操作,適合傳遞給 UI 層。
  • 批量更新:adLockBatchOptimistic + UpdateBatch。
  • 事務:pConn->BeginTrans() / CommitTrans() / RollbackTrans()。
  • 存儲過程:CommandType = adCmdStoredProc,Parameters->Refresh() 自動獲取參數元數據。

掌握 ADO 智能指針模式,能讓數據庫代碼既安全又優雅,是 VC++ 數據訪問層的標準選擇。

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