建立基於對話框的 MFC 應用 `zjy`,點擊按鈕連接本機 SQL Server (Northwind 資料庫),將 `Customers` 資料表內容顯示於報表模式的 `CListCtrl` 中。
#import "C:\Program Files\Common Files\System\ado\msado15.dll" \
no_namespace rename("EOF", "adoEOF")
struct InitOle {
InitOle() { ::CoInitialize(NULL); }
~InitOle() { ::CoUninitialize(); }
} _init_InitOle_;
class CZjyDlg : public CDialog {
// ...
protected:
bool m_IsConnectionOpen = false;
_ConnectionPtr m_pConnection;
_RecordsetPtr m_pRecordset;
// ...
};
BOOL CZjyDlg::OnInitDialog() {
CDialog::OnInitDialog();
// ... 系統選單/圖示初始化 ...
// List Control 報表模式初始化 (插入欄位)
m_list.InsertColumn(0, _T("CustomerID"), LVCFMT_LEFT, 100);
m_list.InsertColumn(1, _T("CompanyName"), LVCFMT_LEFT, 200);
m_list.InsertColumn(2, _T("ContactName"), LVCFMT_LEFT, 150);
m_list.InsertColumn(3, _T("Phone"), LVCFMT_LEFT, 100);
m_list.SetExtendedStyle(LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES);
// ADO 連接與查詢
HRESULT hr;
_bstr_t bstrQuery("SELECT CustomerID, CompanyName, ContactName, Phone FROM Customers");
_bstr_t strConnect = "Provider=SQLOLEDB; Data Source=127.0.0.1; Initial Catalog=Northwind; User ID=sa; Password=;";
_variant_t vNull; vNull.vt = VT_ERROR; vNull.scode = DISP_E_PARAMNOTFOUND;
try {
hr = m_pConnection.CreateInstance(__uuidof(Connection));
if (SUCCEEDED(hr)) {
hr = m_pConnection->Open(strConnect, _bstr_t(L""), _bstr_t(L""), adConnectUnspecified);
if (SUCCEEDED(hr)) {
m_IsConnectionOpen = true;
m_pRecordset = m_pConnection->Execute(bstrQuery, &vNull, adCmdText);
PopulateListCtrl(); // 填充資料
}
}
}
catch (_com_error& e) {
AfxMessageBox(e.ErrorMessage());
}
return TRUE;
}
void CZjyDlg::PopulateListCtrl() {
m_list.DeleteAllItems();
if (!m_pRecordset) return;
int nRow = 0;
while (!m_pRecordset->adoEOF) {
CString strID = (LPCTSTR)_bstr_t(m_pRecordset->Fields->GetItem("CustomerID")->Value);
CString strCompany = (LPCTSTR)_bstr_t(m_pRecordset->Fields->GetItem("CompanyName")->Value);
CString strContact = (LPCTSTR)_bstr_t(m_pRecordset->Fields->GetItem("ContactName")->Value);
CString strPhone = (LPCTSTR)_bstr_t(m_pRecordset->Fields->GetItem("Phone")->Value);
m_list.InsertItem(nRow, strID);
m_list.SetItemText(nRow, 1, strCompany);
m_list.SetItemText(nRow, 2, strContact);
m_list.SetItemText(nRow, 3, strPhone);
nRow++;
m_pRecordset->MoveNext();
}
}
void CZjyDlg::OnCancel() {
if (m_pRecordset) { m_pRecordset->Close(); m_pRecordset = NULL; }
if (m_pConnection && m_IsConnectionOpen) { m_pConnection->Close(); m_IsConnectionOpen = false; }
CDialog::OnCancel();
}
| 環節 | 關鍵代碼/設定 |
|---|---|
| ADO 導入 | `#import msado15.dll rename("EOF","adoEOF")` |
| COM 初始化 | RAII 結構體 `InitOle` 全域實例 |
| 連接字串 | `SQLOLEDB` Provider,指定 Data Source/Initial Catalog/User/Password |
| 執行查詢 | `Connection::Execute` 返回 `_RecordsetPtr` |
| 欄位取值 | `Fields->GetItem("ColumnName")->Value` 轉 `_bstr_t` 再轉 `CString` |
| ListCtrl 報表模式 | `InsertColumn` + `LVS_EX_FULLROWSELECT|LVS_EX_GRIDLINES` |
| 資源釋放 | 關閉 Recordset/Connection,智能指標賦 NULL |
本例展示了 VC+ADO 連接 SQL Server 的最小完整閉環:COM 初始化 → 連接 → 執行查詢 → 綁定 UI → 資源清理。掌握此流程,即可快速構建資料庫前端應用。後續將介紹參數化命令、預存程序調用、事務處理、斷點續傳等進階主題。