環境準備
#import "C:/Program Files/Common Files/System/ado/msado15.dll" \
no_namespace rename("EOF","adoEOF") rename("BOF","adoBOF")
no_namespace 直接使用 ADO 類別名
- 重命名 EOF/BOF 避免與標準宏衝突
連接資料庫
_ConnectionPtr m_pConn;
::CoInitialize(NULL);
try {
m_pConn.CreateInstance(__uuidof(Connection));
_bstr_t strConn = "Provider=SQLOLEDB;Server=.;Database=TestDB;UID=sa;PWD=123;";
m_pConn->Open(strConn, "", "", adModeUnknown);
} catch(_com_error& e) {
AfxMessageBox(e.Description());
return;
}
執行無傳回值 SQL (INSERT/UPDATE/DELETE)
_bstr_t sql = "UPDATE Users SET Name='Tom' WHERE ID=1";
m_pConn->Execute(sql, NULL, adCmdText);
執行有傳回值 SQL (SELECT) → 記錄集
_RecordsetPtr m_pRs;
m_pRs.CreateInstance(__uuidof(Recordset));
_bstr_t sql = "SELECT ID, Name, Age FROM Users";
m_pRs->Open(sql, _variant_t((IDispatch*)m_pConn), adOpenDynamic, adLockOptimistic, adCmdText);
if(!m_pRs->adoEOF) {
while(!m_pRs->adoEOF) {
_variant_t vID = m_pRs->GetCollect("ID");
_variant_t vName = m_pRs->GetCollect("Name");
_variant_t vAge = m_pRs->GetCollect("Age");
// 顯示至 ListCtrl...
m_pRs->MoveNext();
}
}
m_pRs->Close();
呼叫無傳回值預存程序 (帶參數)
_CommandPtr cmd; cmd.CreateInstance(__uuidof(Command));
cmd->ActiveConnection = m_pConn;
cmd->CommandType = adCmdStoredProc;
cmd->CommandText = "proc_DeleteUser";
_ParameterPtr p1, p2;
p1 = cmd->CreateParameter("Flag", adTinyInt, adParamInput, 1, _variant_t((BYTE)1));
cmd->Parameters->Append(p1);
p2 = cmd->CreateParameter("UserID", adInteger, adParamInput, 4, _variant_t(100));
cmd->Parameters->Append(p2);
try { cmd->Execute(NULL, NULL, adCmdStoredProc); }
catch(...) { /* 錯誤處理 */ }
呼叫有傳回記錄集的預存程序
// 方式 1: 用 Execute 直接取回 Recordset
_RecordsetPtr rs = m_pConn->Execute("EXEC proc_GetUsers 1", NULL, adCmdText);
// ... 同 SELECT 處理 ...
// 方式 2: Command 物件 (支援輸出參數)
_CommandPtr cmd; cmd.CreateInstance(__uuidof(Command));
cmd->ActiveConnection = m_pConn;
cmd->CommandType = adCmdStoredProc;
cmd->CommandText = "proc_GetUsersWithCount";
_ParameterPtr pOut = cmd->CreateParameter("TotalCount", adInteger, adParamOutput, 4);
cmd->Parameters->Append(pOut);
_RecordsetPtr rs = cmd->Execute(NULL, NULL, adCmdStoredProc);
// 讀取 rs...
long total = pOut->Value.lVal; // 取得輸出參數
資源釋放順序
- Recordset
Close()
- Connection
Close()
::CoUninitialize()
實戰提示
- 連接字串建議存
.ini 或註冊表,GetPrivateProfileString 讀取
- 大量資料考慮
adUseClient 游標離線操作
_variant_t 取值前檢查 vt == VT_NULL 避免轉換例外
- 多執行緒每緒獨立
CoInitialize + 連接物件