msado15.dll 產生 .tlh/.tli,自動產生智慧指標類別(_ConnectionPtr 等),語法簡潔、型別安全。IDispatch,較繁瑣但可控制細節。CLSIDFromProgID + CoCreateInstance,效率最高、執行檔最小、控制力最強,但程式碼最複雜。// stdafx.h
#import "C:\Program Files\Common Files\System\ado\msado15.dll" \
no_namespace rename("EOF", "adoEOF") rename("BOF", "adoBOF")
// 初始化 COM(在 CWinApp::InitInstance)
AfxOleInit(); // 或 ::CoInitialize(NULL),對應 ExitInstance 呼叫 ::CoUninitialize()
// 1. 建立連線
_ConnectionPtr pConn = NULL;
HRESULT hr = pConn.CreateInstance(__uuidof(Connection));
if (FAILED(hr)) return;
_bstr_t strConn = "Provider=SQLOLEDB; Server=MyServer; Database=MyDB; uid=sa; pwd=sa;";
try {
pConn->Open(strConn, "", "", adConnectUnspecified);
} catch (_com_error &e) {
AfxMessageBox(e.Description());
return;
}
// 2. 開啟記錄集
_RecordsetPtr pRs;
hr = pRs.CreateInstance(__uuidof(Recordset));
if (FAILED(hr)) return;
try {
pRs->Open(_variant_t("UserInfo"), _variant_t((IDispatch*)pConn),
adOpenKeyset, adLockOptimistic, adCmdTable);
} catch (_com_error &e) {
AfxMessageBox("無法開啟 UserInfo 資料表");
return;
}
// 3. 讀取資料
try {
pRs->MoveFirst();
while (pRs->adoEOF == VARIANT_FALSE) {
CString name = (LPCTSTR)(_bstr_t)pRs->Fields->GetItem(_variant_t("UserName"))->Value;
AfxMessageBox(name);
pRs->MoveNext();
}
} catch (_com_error &e) {
AfxMessageBox(e.Description());
}
// 4. 修改資料
try {
pRs->MoveFirst();
while (pRs->adoEOF == VARIANT_FALSE) {
pRs->Fields->GetItem(_variant_t("Address"))->Value = _bstr_t("北京大學");
pRs->Update();
pRs->MoveNext();
}
} catch (_com_error &e) {
AfxMessageBox(e.Description());
}
// 5. 新增、刪除、參數化命令、事件、資料繫結、篩選/排序、交易處理等進階主題請參考 MSDN 文件。
_ConnectionPtr:封裝 Connection 物件的 IDispatch 指標,提供 Open/Close/Execute 等方法。_RecordsetPtr:封裝 Recordset,支援游標型別(adOpenKeyset 等)、鎖定型別(adLockOptimistic)、導航(MoveFirst/Next)、欄位存取(Fields->GetItem)。_variant_t、_bstr_t:VARIANT/BSTR 智慧封裝,自動處理參考計數與型別轉換。統一使用 try/catch(_com_error &e) 捕獲 ADO/COM 錯誤,e.Description() 取得詳細訊息,e.Error() 取得 HRESULT。
Command 物件 + 參數化 SQL,避免逐列 Update。adOpenForwardOnly + adLockReadOnly 唯讀前向游標以提高查詢速度。