MFC DAO 類別 (CDaoDatabase、CDaoRecordset 等) 功能強大但使用繁瑣。本文設計一個 CDataBaseOperate 封裝類,整合開啟資料庫、開啟資料表/查詢、條件篩選記錄集、資源自動管理 (RAII 風格) 等常用操作,支援對話框專案直接使用,無需文檔/視圖架構。
class CDataBaseOperate {
private:
// 連接字串 (ODBC DSN=sql-database, UID=sa, PWD=pass)
#define SQL_DATABASE _T("ODBC;DSN=sql-database;UID=sa;PWD=pass;")
CDaoDatabase* m_pDatabase; // 資料庫連接
CDaoTableDef* m_pTableDef; // 資料表定義
CDaoRecordset m_Recordset; // 記錄集 (值語義,隨類生命週期)
CDaoQueryDef* m_pQueryDef; // 查詢定義
long m_nRecordCount; // 記錄總數快取
public:
CDataBaseOperate(); // 建構: new 指針物件
~CDataBaseOperate(); // 析構: delete 指針物件
BOOL OpenDatabase(); // 開啟資料庫
BOOL OpenTable(CString table, long difficulty=0); // 開啟表並查詢
void CloseTable(); // 關閉表並釋放指針
// ... 記錄導航、增刪改查封裝 ...
};
CDataBaseOperate::CDataBaseOperate() {
m_pDatabase = new CDaoDatabase;
m_pTableDef = NULL; m_pQueryDef = NULL;
m_nRecordCount = 0;
}
CDataBaseOperate::~CDataBaseOperate() {
CloseTable(); // 確保釋放 Table/Query 指針
if (m_pDatabase) {
if (m_pDatabase->IsOpen()) m_pDatabase->Close();
delete m_pDatabase; m_pDatabase = NULL;
}
}
BOOL CDataBaseOperate::OpenTable(CString strTableName, long lDifficulty) {
if (!OpenDatabase()) return FALSE;
m_pTableDef = new CDaoTableDef(m_pDatabase);
if (!m_pTableDef->Open(strTableName)) { delete m_pTableDef; return FALSE; }
// 構建 SQL
CString sql;
if (lDifficulty == 0) {
sql.Format(_T("SELECT * FROM [%s]"), strTableName);
} else {
sql.Format(_T("SELECT * FROM [%s] WHERE [難度係數] = %ld"), strTableName, lDifficulty);
}
m_pQueryDef = new CDaoQueryDef(m_pDatabase);
m_pQueryDef->Create(NULL, sql); // 建立查詢
m_Recordset.Open(m_pQueryDef); // 開啟記錄集
// 計算記錄數 (移動到末尾)
m_nRecordCount = 0;
while (!m_Recordset.IsEOF()) { m_nRecordCount++; m_Recordset.MoveNext(); }
m_Recordset.MoveFirst();
return TRUE;
}
void CDataBaseOperate::CloseTable() {
if (m_pQueryDef) { delete m_pQueryDef; m_pQueryDef = NULL; }
if (m_pTableDef) { delete m_pTableDef; m_pTableDef = NULL; }
// m_Recordset 為值成員,隨類銷毀自動 Close
}
// 主對話框 .h
#include "DataBaseOperate.h"
class CMyDlg : public CDialog {
CDataBaseOperate m_db; // 成員變數
// ...
};
// 具體操作 .cpp
void CMyDlg::OnBtnQuery() {
if (!m_db.OpenTable(_T("Questions"), 2)) { // 查難度=2
AfxMessageBox(_T("開啟資料表失敗"));
return;
}
// 遍歷顯示
while (!m_db.m_Recordset.IsEOF()) {
CString name = m_db.m_Recordset.GetFieldValue(_T("正題內容"));
// ... 更新 UI ...
m_db.m_Recordset.MoveNext();
}
m_db.CloseTable();
}
CRecordView/CDaoRecordView 文檔視圖架構。m_strFilter 更直觀強大。new/delete,避免洩漏。InsertRecord、UpdateRecord、DeleteRecord、ExecuteSQL 等封裝方法。此類已在多個 MFC + Access/SQL Server 專案中穩定運行,歡迎直接複用擴展。