首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> VC >> 關於VC++

ADO 封裝類實戰教學 (下):從 COM 初始化到查詢工具完整實作

     編輯:關於VC++

環境建置與 COM 初始化

// 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(); // 僅能呼叫一次,切勿重複

CAdoConnection 連線封裝

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;

CAdoRecordSet 記錄集封裝

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"));

實戰:SQL 查詢工具完整實作

1. 介面架構

  • CLogoDig:資料來源選擇對話框 (Access/SQL Server)
  • CCoolControlBar:可調整大小的控制列 (左側樹狀結構)
  • CMSFlexGrid:Microsoft FlexGrid ActiveX 控制項 (結果顯示)
  • 兩個 Edit 控制項:SQL 輸入區、錯誤訊息區

2. 連線處理

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(); // 重新整理資料庫樹
    }
}

3. 查詢執行與 FlexGrid 繫結

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; }
}

4. 資料庫結構揭漏:樹狀檢視表/欄位

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 等枚舉值查詢其他中繼資料。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved