MFC封裝ODBC提供三大核心類別:
| 類型 | 特點 | 適用場景 |
|---|---|---|
| Snapshot (快照) | 一次性下載所有記錄,靜態視圖,網路負擔大但後續無網路流量,效能佳 | 小型資料集、唯讀報表、不需即時同步 |
| Dynaset (動態集) | 指標式存取,按需下載,即時反映他人異動,適合編輯、大型資料庫 | 資料編輯會話、大型資料庫、需即時同步 |
包含標頭檔afxdb.h,使用AppWizard建立ODBC專案框架或手動建立。
必須從CRecordset衍生自訂類別,宣告對應資料表欄位的成員變數,並覆寫DoFieldExchange:
class CMyRecordset : public CRecordset {
public:
CString m_strName;
int m_nAge;
// ... 其他欄位
virtual void DoFieldExchange(CFieldExchange* pFX) {
pFX->SetFieldType(CFieldExchange::outputColumn);
RFX_Text(pFX, _T("[Name]"), m_strName);
RFX_Int(pFX, _T("[Age]"), m_nAge);
// ... 其他RFX函數
}
};
CDatabase db;
db.Open(_T("MyDSN")); // 建立ODBC連接
CMyRecordset rs1, rs2;
rs1.m_pDatabase = &db; // 共享同一連接
rs2.m_pDatabase = &db;
// 或直接建構時指定
CMyRecordset rs3(&db);
// 使用預設SQL (GetDefaultSQL傳回)
rs.Open();
// 指定自訂SQL
CString strSQL = _T("SELECT * FROM Employee WHERE Dept='RD'");
rs.Open(AFX_DATABASE_USE_DEFAULT, strSQL);
// 使用成員變數篩選/排序
rs.m_strFilter = _T("Dept='RD'");
rs.m_strSort = _T("Salary DESC");
rs.Requery();
// 參數化查詢 (防SQL注入、效能更好)
// 步驟:宣告參數 -> 建構函數初始化 -> DoFieldExchange綁定 -> 設定值 -> Requery
rs.m_strFilter = _T("Dept=? AND Salary>?");
rs.m_strParamDept = _T("RD");
rs.m_dParamSalary = 50000.0;
rs.Requery(); // 參數按綁定順序替換?
rs.MoveFirst(); rs.MoveNext(); rs.MovePrev(); rs.MoveLast();
rs.Move(n); // 相對移動
// 搭配IsBOF()/IsEOF()判斷邊界
rs.AddNew(); // 準備新記錄
rs.m_strName = _T("王小明");
rs.m_nAge = 28;
// ... 設定其他欄位
rs.Update(); // 寫入資料庫
rs.Requery(); // 重建記錄集含新記錄
rs.Delete(); // 刪除當前記錄,無需Update
if (!rs.IsEOF()) rs.MoveNext(); // 移至下一筆
else rs.MoveLast(); // 或移至最後一筆
rs.Edit(); // 進入編輯模式
rs.m_nAge = 29; // 修改欄位
rs.Update(); // 提交變更
rs.Requery();
// 方法1: 移動至最後取得記錄數 (需開啟動態集)
rs.Open(CRecordset::dynaset);
rs.MoveLast();
long count = rs.GetRecordCount();
// 方法2: 使用COUNT(*) SQL查詢 (效能最佳)
CRecordset rsCount(&db);
rsCount.Open(CRecordset::snapshot, _T("SELECT COUNT(*) FROM Employee"));
rsCount.GetFieldValue(_T("COUNT(*)"), varCount);
TRY/CATCH(CDBException, e)捕捉資料庫例外MFC ODBC類別大幅簡化資料庫開發,掌握CDatabase連接管理、CRecordset衍生與RFX機制、各類查詢模式與CRUD操作流程,即可高效建構穩健的資料庫應用程式。