ODBC (Open Database Connectivity) 通過驅動程序屏蔽底層 DBMS 差異,提供統一 C API。MFC 在此基礎上封裝了三大核心類,極大簡化開發。
| 類 | 角色 | 關鍵功能 |
|---|---|---|
CDatabase | 數據源連接 | OpenEx()、ExecuteSQL()、事務控制 |
CRecordset | 記錄集 (結果集) | Open()、Requery()、MoveNext()、AddNew/Edit/Delete/Update、篩選/排序 |
CRecordView | 數據綁定視圖 | 將記錄集字段自動綁定到對話框控件 |
File → New → Projects → MFC AppWizard (exe)Super_ES)。CRecordset 派生類包含字段映射 (RFX) 代碼。
CDatabase db;
if (!db.OpenEx(_T("DSN=Super_ES;UID=sa;PWD=;"), CDatabase::noOdbcDialog)) {
AfxMessageBox(_T("連接失敗"));
return;
}
CMyRecordSet rs(&db); // 傳入已打開的 db,復用連接
// 或使用默認連接
// CMyRecordSet rs; rs.m_pDatabase = &db;
rs.m_strFilter = _T("TYPE='電動機'"); // WHERE 條件
rs.m_strSort = _T("VOLTAGE"); // ORDER BY
rs.Open(CRecordset::dynaset); // 或 snapshot
while (!rs.IsEOF()) {
// 訪問字段:rs.m_fieldName
rs.MoveNext();
}
rs.Close();
// 在 Recordset 派生類中聲明參數
CString m_paramType;
double m_paramVoltage;
// DoFieldExchange 中綁定
pFX->SetFieldType(CFieldExchange::param);
RFX_Text(pFX, _T("P1"), m_paramType);
RFX_Double(pFX, _T("P2"), m_paramVoltage);
m_nParams = 2;
// 使用
rs.m_strFilter = _T("TYPE=? AND VOLTAGE=?");
rs.m_paramType = _T("電動機");
rs.m_paramVoltage = 60.0;
rs.Requery();
rs.AddNew(); // 準備新記錄
rs.m_type = _T("發電機");
rs.m_voltage = 220.0;
// ... 設置其他字段
rs.Update(); // 寫入數據庫
rs.Requery(); // 刷新記錄集
rs.Edit(); // 進入編輯模式
rs.m_type = _T("變壓器");
rs.Update(); // 提交修改
rs.Requery();
rs.Delete(); // 立即刪除,無需 Update
if (!rs.IsEOF()) rs.MoveNext();
else rs.MoveLast();
rs.Move(AFX_MOVE_REFRESH); // 放棄 AddNew/Edit,恢復原狀態
CDatabase db;
db.OpenEx(_T("DSN=Super_ES"), 0);
CRecordSet rs1, rs2;
rs1.m_pDatabase = &db;
rs2.m_pDatabase = &db;
rs1.Open(...);
rs2.Open(...);
// 共享同一物理連接,節省資源
BOOL ExecuteSQLAndReport(CDatabase *pdb, const CString& sql) {
TRY {
pdb->ExecuteSQL(sql); // 直接執行任意 SQL
return TRUE;
}
CATCH(CDBException, e) {
CString msg; msg.LoadString(IDS_EXECUTE_SQL_FAILED);
msg += sql;
AfxMessageBox(msg);
return FALSE;
}
END_CATCH
}
// 用法
ExecuteSQLAndReport(&db, _T("CREATE TABLE Temp (ID INT PRIMARY KEY, Name VARCHAR(50))"));
ExecuteSQLAndReport(&db, _T("DELETE FROM Logs WHERE Date < '2020-01-01'"));
⚠️ 直接 SQL 破壞 DBMS 無關性,謹慎使用。
TRY {
rs.Open(...);
}
CATCH(CDBException, e) {
CString err; e->GetErrorMessage(err.GetBuffer(255), 255);
AfxMessageBox(_T("數據庫錯誤: ") + err);
}
END_CATCH
OpenEx 檢查返回值,失敗提示用戶。? 佔位符) 防 SQL 注入。AddNew/Edit 後必須 Update 提交。IsEOF/IsBOF。CDatabase,不可跨線程共享。Close() 記錄集/數據庫 → 連接洩漏。ExecuteSQL 返回影響行數 (ODBC 不保證)。MFC ODBC 類 (CDatabase/CRecordset/CRecordView) 將底層 ODBC API 封裝為直觀的 C++ 接口。掌握連接管理、記錄集打開模式 (dynaset/snapshot)、RFX 字段映射、參數化查詢、CRUD 標準流程、連接復用、直接 SQL 執行,即可高效開發健壯的數據庫應用。異常處理與資源釋放是生產級代碼的必修課。