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

VC++ ADO 資料庫程式設計完整指南:從 #import 到 Recordset 進階操作

     編輯:關於C語言

ADO(ActiveX Data Objects)作為 Microsoft 推薦的下一代資料存取介面,以 COM 為基礎、封裝 OLE DB、支援多語言與腳本,極大簡化了資料庫程式開發。本文詳細說明 VC++ 中引入 ADO 型別庫、初始化 COM 環境、三大核心介面(_ConnectionPtr、_CommandPtr、_RecordsetPtr)的選擇策略,並提供連接字串、SQL 執行、斷點續傳等實戰範例。

環境建置:引入 ADO 型別庫

在 stdafx.h 最前端加入:

#define INITGUID
#import "C:\\Program Files\\Common Files\\System\\ado\\msado15.dll" \
    no_namespace rename("EOF", "EndOfFile")
#include <icrsint.h>
  • no_namespace:避免 using namespace ADODB;,簡化程式碼。
  • rename("EOF", "EndOfFile"):避免與 C++ 標準庫 EOF 衝突。
  • 路徑視 ADO 安裝位置調整,VC6 預設為 msado15.dll(ADO 2.5/2.6/2.7 通用)。

COM 環境初始化與釋放


// 程式啟動時(如 CWinApp::InitInstance)
::CoInitialize(NULL); // 或 CoInitializeEx(NULL, COINIT_APARTMENTTHREADED)

// 程式結束時(如 CWinApp::ExitInstance)
::CoUninitialize();

若遺漏 CoInitialize,所有 ADO 呼叫將拋出 CO_E_NOTINITIALIZED 錯誤。

三大核心介面選擇策略

介面適用場景特點
_ConnectionPtr建立長連線、執行無傳回結果的 SQL(DDL、存儲過程)、交易控制連線池管理、交易支援
_CommandPtr參數化查詢、預存程序、需重複執行的 SQL參數集合、Prepared Statement
_RecordsetPtr單次查詢、游標操作、鎖定控制、資料導航功能最豐富、可獨立建立連線

連接字串範例

DSN 方式

_ConnectionPtr pConn;
pConn.CreateInstance(__uuidof(Connection));
pConn->Open("DSN=MyDSN;UID=sa;PWD=123", "", "", adConnectUnspecified);

DSN-less 方式(部署免設定 ODBC)

// SQL Server (SQLOLEDB Provider)
pConn->Open("Provider=SQLOLEDB;Server=.;Database=TestDB;UID=sa;PWD=123", "", "", adConnectUnspecified);

// Access (Jet OLEDB)
pConn->Open("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=db.mdb;", "", "", adConnectUnspecified);

// Access 2007+ (ACE OLEDB)
pConn->Open("Provider=Microsoft.ACE.OLEDB.12.0;Data Source=db.accdb;", "", "", adConnectUnspecified);

Recordset 核心操作範例

開啟 Recordset(獨立連線模式)

_RecordsetPtr pRs;
pRs.CreateInstance(__uuidof(Recordset));
pRs->Open("SELECT * FROM Employees WHERE DeptID = 10",
          "Provider=SQLOLEDB;Server=.;Database=HR;UID=sa;PWD=123",
          adOpenStatic, adLockOptimistic, adCmdText);

游標類型與鎖定類型選擇

游標類型特點適用場景
adOpenForwardOnly唯前向、唯讀、最快報表列印、單向掃描
adOpenStatic靜態快照、可捲動、不見他人變更離線分析、報表
adOpenKeyset鍵集游標、見他人修改、不見新增/刪除一般編輯介面
adOpenDynamic動態、見所有變更、支援書籤高併發即時協作
鎖定類型說明
adLockReadOnly唯讀(預設)
adLockOptimistic樂觀鎖定,更新時檢查衝突
adLockPessimistic悲觀鎖定,編輯即鎖定
adLockBatchOptimistic批次更新模式,配合 UpdateBatch

欄位存取與導航

// 依欄位名稱存取(推薦)
_variant_t vName = pRs->GetCollect("Name"); // 回傳 _variant_t
CString strName = (LPCTSTR)(_bstr_t)vName;  // 轉 CString

// 依索引存取(較快)
_variant_t v = pRs->Fields->GetItem(0)->Value;

// 導航
pRs->MoveFirst();
pRs->MoveNext();
pRs->MovePrevious();
pRs->MoveLast();
if (pRs->EndOfFile) { /* 結束 */ }

新增/修改/刪除

// 新增
pRs->AddNew();
pRs->PutCollect("Name", _variant_t("New Employee"));
pRs->PutCollect("Salary", _variant_t(50000));
pRs->Update();

// 修改
pRs->Edit();
pRs->PutCollect("Salary", _variant_t(55000));
pRs->Update();

// 刪除
pRs->Delete(adAffectCurrent);

進階主題

參數化查詢(防 SQL Injection)

_CommandPtr pCmd;
pCmd.CreateInstance(__uuidof(Command));
pCmd->ActiveConnection = pConn;
pCmd->CommandText = "SELECT * FROM Users WHERE UserID = ? AND Status = ?";
pCmd->CommandType = adCmdText;

// 附加參數(順序必須與 SQL 佔位符一致)
pCmd->Parameters->Append(pCmd->CreateParameter("UserID", adInteger, adParamInput, 4, 1001));
pCmd->Parameters->Append(pCmd->CreateParameter("Status", adVarChar, adParamInput, 20, "Active"));

_RecordsetPtr pRs = pCmd->Execute(NULL, NULL, adCmdText);

斷點續傳大檔案(GetChunk/AppendChunk)

// 讀取長二進位欄位
long offset = 0, chunkSize = 8192;
CFile file("output.dat", CFile::modeCreate | CFile::modeWrite);
while (!pRs->EndOfFile) {
    _variant_t chunk = pRs->GetCollect("Photo").GetChunk(chunkSize);
    long actualLen = V_ARRAY(&chunk)->rgsabound[0].cElements;
    if (actualLen == 0) break;
    file.Write(V_ARRAY(&chunk)->pvData, actualLen);
    offset += actualLen;
}
file.Close();

交易控制

pConn->BeginTrans();
try {
    pConn->Execute("INSERT ...", NULL, adExecuteNoRecords);
    pConn->Execute("UPDATE ...", NULL, adExecuteNoRecords);
    pConn->CommitTrans();
} catch (_com_error &e) {
    pConn->RollbackTrans();
    AfxMessageBox(e.Description());
}

錯誤處理模式

try {
    // ADO 操作
} catch (_com_error &e) {
    CString msg;
    msg.Format(_T("ADO 錯誤: 0x%08X - %s"), e.Error(), e.ErrorMessage());
    AfxMessageBox(msg);
    // 可進一步檢查 pConn->Errors 集合
}

總結

ADO 以 COM 封裝 OLE DB,提供 _ConnectionPtr/_CommandPtr/_RecordsetPtr 三大智慧指標介面,配合 #import 型別庫自動產生的包裝類別,使 VC++ 資料庫程式碼簡潔、型別安全、部署彈性(DSN-less)。掌握連接字串、游標/鎖定選擇、參數化查詢與交易控制,即可應對企業級資料庫應用開發。

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