// Stdafx.h 引入 ADO 類型庫
#import "c:\program files\common files\system\ado\msado15.dll" \
no_namespace rename("EOF", "adoEOF")
// 編譯警告 C4146 抑制 (MSDN 建議忽略,或加入下行)
#pragma warning(disable:4146)
// App::InitInstance 中一次性初始化 COM
AfxOleInit(); // 僅能呼叫一次,切勿重複
BOOL CAdoConnection::Connect(LPCTSTR strConnect, long lOptions) {
m_strConnect = strConnect;
try {
HRESULT hr = m_pConnection.CreateInstance(_T("ADODB.Connection"));
if (SUCCEEDED(hr)) {
if (SUCCEEDED(m_pConnection->Open(strConnect, _T(""), _T(""), lOptions)))
return TRUE;
}
} catch (_com_error e) {
TRACE(_T("連線錯誤: %s\n"), e.ErrorMessage());
} catch (...) { TRACE(_T("未知連線錯誤")); }
return FALSE;
}
連線字串範例:
// Access
CString strConnect = _T("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=") + strSrcName;
// SQL Server
CString strConnect = _T("Provider=SQLOLEDB.1;Data Source=") + server
+ _T(";Initial Catalog=") + db
+ _T(";User ID=") + uid + _T(";PWD=") + pwd;
HRESULT CAdoRecordSet::Open(LPCTSTR strSQL, long lOption,
CursorTypeEnum CursorType, LockTypeEnum LockType) {
try {
if (!m_pConnection) return -1;
if (!m_pRecordset) m_pRecordset.CreateInstance(_T("ADODB.Recordset"));
m_pRecordset->Open(_bstr_t(strSQL),
_variant_t((IDispatch*)m_pConnection->GetConnection(), true),
CursorType, LockType, lOption);
return (m_pRecordset->adoEOF) ? 0 : 1; // 1=有資料, 0=空集合, -1=錯誤
} catch (_com_error e) {
TRACE(_T("Open 錯誤: %s\n"), e.ErrorMessage());
return -1;
}
}
使用範例:
CAdoRecordSet rset;
rset.SetAdoConnection(&(GetDocument()->m_adoConnection)); // 必須先指定連線
rset.Open(_T("select * from city"));
CLogoDig:資料來源選擇對話框 (Access/SQL Server)CCoolControlBar:可調整大小的控制列 (左側樹狀結構)CMSFlexGrid:Microsoft FlexGrid ActiveX 控制項 (結果顯示)void CAccessView::OnFileConnect() {
CLogoDig dlg;
if (dlg.DoModal() == IDOK) {
CString strConnect;
if (dlg.m_nSrcType == 0) // Access
strConnect = _T("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=") + dlg.m_strSrcName;
else // SQL Server
strConnect = _T("Provider=SQLOLEDB.1;Data Source=") + dlg.m_strSrcName
+ _T(";Initial Catalog=") + dlg.m_strDbName
+ _T(";User ID=") + dlg.m_strUserName + _T(";PWD=") + dlg.m_strPassWord;
GetDocument()->m_adoConnection.Disconnect();
if (!GetDocument()->m_adoConnection.Connect(strConnect)) {
AfxMessageBox(_T("連線失敗!")); return;
}
((CMainFrame*)GetParentFrame())->m_wndLeftBar.InitTree(); // 重新整理資料庫樹
}
}
void CAccessView::UpdateGrid() {
if (!GetDocument()->m_adoConnection.IsOpen()) {
AfxMessageBox(_T("資料庫未開啟!")); return;
}
m_wndGrid.ShowWindow(SW_HIDE);
m_editError.ShowWindow(SW_HIDE);
CAdoRecordSet rset;
rset.SetAdoConnection(&(GetDocument()->m_adoConnection));
if (rset.Open(m_strSQL, adCmdText) != 1) {
m_strError = GetDocument()->m_adoConnection.GetLastError();
UpdateData(FALSE);
m_editError.ShowWindow(SW_SHOW);
return;
}
try {
int nrow = rset.GetRecordCount();
int ncol = rset.GetFields()->Count;
m_wndGrid.SetCols(ncol);
m_wndGrid.SetRows(nrow + 1); // +1 顯示欄位名
m_wndGrid.SetFixedCols(0);
// 填入欄位名
m_wndGrid.SetRow(0);
for (int i=0; i<ncol; i++) {
m_wndGrid.SetCol(i);
m_wndGrid.SetText(rset.GetFieldName(i));
int nwidth = min(rset.GetFieldDefineSize(i) * 200, 2000);
m_wndGrid.SetColWidth(i, nwidth);
}
// 填入資料
int n = 1;
CString value;
while (!rset.IsEOF()) {
m_wndGrid.SetRow(n++);
for (int i=0; i<ncol; i++) {
m_wndGrid.SetCol(i);
rset.GetValueString(value, i);
m_wndGrid.SetText(value);
}
rset.MoveNext();
}
m_wndGrid.ShowWindow(SW_SHOW);
} catch (_com_error) { return; }
}
void CLeftBar::InitTree() {
CAdoRecordSet rset;
CString strTablename;
HTREEITEM item = TVI_ROOT;
try {
if (GetDocument()->m_adoConnection.GetConnection()->State != adStateOpen) return;
m_ctrlTree.DeleteAllItems();
// OpenSchema 取得欄位中繼資料
rset = GetDocument()->m_adoConnection.OpenSchema(adSchemaColumns);
while (!rset.IsEOF()) {
CString strValue;
rset.GetValueString(strValue, _T("TABLE_NAME"));
if (strValue != strTablename) {
strTablename = strValue;
item = m_ctrlTree.InsertItem(strTablename, 1, 1);
}
_bstr_t Value = rset.GetFields()->Item[L"COLUMN_NAME"]->Value;
m_ctrlTree.InsertItem((LPCTSTR)Value, 2, 2, item);
rset.MoveNext();
}
} catch(_com_error) { }
}
同樣可用 adSchemaTables、adSchemaIndexes、adSchemaViews 等枚舉值查詢其他中繼資料。