為了替女友開發個人記帳小系統,筆者在 VC++ 6.0 中使用 ADO (ActiveX Data Objects) 操作 Access 資料庫,整理出一套實用開發模式與常用操作範本,供同好參考。
// 1. 匯入 ADO 型別庫 (msado15.dll),重新命名 EOF 避免衝突
#import "c:\program files\common files\system\ado\msado15.dll" \
no_namespace rename("EOF", "adoEOF")
// 2. 初始化 COM 程式庫
// MFC 專案:AfxOleInit();
// 非 MFC:CoInitialize(NULL); ... CoUninitialize();
// 3. 三大智慧指標
_ConnectionPtr m_pConnection; // 連線
_RecordsetPtr m_pRecordset; // 記錄集
_CommandPtr m_pCommand; // 命令
// 連線 Access (Jet OLEDB 4.0)
m_pConnection.CreateInstance(__uuidof(Connection));
try {
m_pConnection->Open("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=Demo.mdb", "", "", adModeUnknown);
} catch (_com_error& e) {
AfxMessageBox("資料庫連接失敗,確認 Demo.mdb 路徑!");
return FALSE;
}
// 設定連線逾時 (秒)
m_pConnection->put_ConnectionTimeout(5);
// 關閉連線
if (m_pConnection->State) m_pConnection->Close();
m_pConnection = NULL;
m_pRecordset.CreateInstance(__uuidof(Recordset));
try {
m_pRecordset->Open("SELECT * FROM DemoTable",
m_pConnection.GetInterfacePtr(),
adOpenDynamic, adLockOptimistic, adCmdText);
} catch (_com_error* e) {
AfxMessageBox(e->ErrorMessage());
}
while (!m_pRecordset->adoEOF) {
_variant_t var;
var = m_pRecordset->GetCollect("Name"); // 依欄位名
if (var.vt != VT_NULL) strName = (LPCSTR)_bstr_t(var);
var = m_pRecordset->GetCollect("Age"); // 或依索引
// var = m_pRecordset->GetCollect(_variant_t((long)0));
m_AccessList.AddString(strName + " --> " + strAge);
m_pRecordset->MoveNext();
}
m_pRecordset->Close();
m_pRecordset->AddNew();
m_pRecordset->PutCollect("Name", _variant_t("Wang"));
m_pRecordset->PutCollect("Age", _variant_t(25));
m_pRecordset->Update();
m_pRecordset->MoveFirst();
m_pRecordset->Move(1); // 移至第 2 筆 (0-based)
m_pRecordset->Delete(adAffectCurrent); // 刪除當前記錄
m_pRecordset->Update();
m_pCommand.CreateInstance(__uuidof(Command));
m_pCommand->ActiveConnection = m_pConnection;
m_pCommand->CommandText = "SELECT * FROM DemoTable WHERE Age > ?";
m_pCommand->Parameters->Append(m_pCommand->CreateParameter("Age", adInteger, adParamInput, 4, 20));
m_pRecordset = m_pCommand->Execute(NULL, NULL, adCmdText);
_variant_t recordsAffected;
// 更新
m_pConnection->Execute("UPDATE Users SET Old = Old + 1", &recordsAffected, adCmdText);
// 呼叫預存程序
m_pConnection->Execute("MyProc", &recordsAffected, adCmdStoredProc);
_RecordsetPtr pSchema = m_pConnection->OpenSchema(adSchemaTables);
while (!pSchema->adoEOF) {
_bstr_t tableName = pSchema->Fields->GetItem("TABLE_NAME")->Value;
_bstr_t tableType = pSchema->Fields->GetItem("TABLE_TYPE")->Value;
if (strcmp((LPCSTR)tableType, "TABLE") == 0) {
AfxMessageBox((LPCSTR)tableName); // 只顯示使用者資料表
}
pSchema->MoveNext();
}
pSchema->Close();
Fields* pFields = NULL;
m_pRecordset->get_Fields(&pFields);
long colCount; pFields->get_Count(&colCount);
for (long i = 0; i < colCount; i++) {
Field* pField = NULL;
pFields->get_Item(_variant_t(i), &pField);
BSTR bstrName; pField->get_Name(&bstrName);
m_FieldsList.AddString((LPCSTR)bstrName);
pField->Release();
}
pFields->Release();
| 轉換方向 | 程式碼 |
|---|---|
| _variant_t → long | (long)var |
| _variant_t → CString | CString str = (LPCSTR)_bstr_t(var); |
| CString → _variant_t | _variant_t v(strSql); |
| CString → BSTR | BSTR bstr = strSql.AllocSysString(); |
| BSTR → CString | CString str = (LPCSTR)bstr; |
| CString → _bstr_t | _bstr_t bstr = (_bstr_t)strSql; |
| _bstr_t → CString | CString str = (LPCSTR)bstr; |
#2004-4-5#'2004-4-5'SELECT * FROM MyTable WHERE DateField > #2004-4-10#
本文範例專案包含完整記帳系統原始碼,涵蓋收入/支出分類、月報表、圖表統計等功能,是 VC++ 6.0 + ADO + Access 經典三層架構的優良入門教材。