五、開始編寫ADO應用程序.
使用ADO之前,我們另外還需要添加下面的語句,如此把ADO的庫引入到工程中
. #import "c:\program files\common files\system\ado\msado15.dll"
no_namespace rename("EOF","adoEOF")
根據機器安裝時候的設置不同具體的路徑可能不一樣。
另外編譯的時候會出現如下的警告信息:
msado15.tlh(405) : warning C4146: unary minus operator applied to unsigned type, result still unsigned
MSDN建議我們不要理會。如果你實在不想看到的話可以在stdafx.h中加入一行下面的代碼:
#pragma warning(disable:4146)
這樣這個警告信息就不會再出現了。
ADO使用了COM,所以在使用ADO之前,必須對COM進行了初始化,否則無法使用.你可以使用AfxOleInit()來初始化,但只能初始一次,你不能多次調用此函數,建議你在應用程序的APP類的InitInstance方法中進行初始化.
上面這些一般相關的資料都有詳細說明,因此我就不細說了,下面我們來看看如何我封裝的兩個類。
六、ADO封裝類:CAdoConnection 和 CAdoRecordSet
首先當然是要連接到數據源了,連接到數據源的函數是_CAdoConnection的Connect方法,它封裝了ADO連接對象的CreateInstance和Open方法:
我們來看看我是如何封裝的:
BOOL CAdoConnection::Connect(LPCTSTR strConnect, long lOptions)
{
m_strConnect = strConnect;
try
{
///創建 Connection 對象---------------------------
HRESULT hr = m_pConnection.CreateInstance("ADODB.Connection");
if (SUCCEEDED(hr))
{
// 連接數據庫---------------------------------------------
if (SUCCEEDED(m_pConnection->Open(strConnect, "", "", lOptions)))
{
return TRUE;
}
}
}
catch (_com_error e)
{
TRACE(_T(":( 連接數據庫發生錯誤: %s\n"), e.ErrorMessage());
return FALSE;
}
catch (...)
{
TRACE(_T(":( 連接數據庫時發生未知錯誤:"));
}
return FALSE;
}
使用之前先定義一個CAdoConnection 類對象如m_adoConnection,例如:
CString strSrcName = "E:\\Access\\datebase.mdb";//假設在e盤有這樣一個access的數據庫文件
CString strConnect = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + strSrcName;
m_adoConnection.Connect(LPCSTR(strConnect));
這樣就連接到數據源了.
接著就是要打開記錄集了,下面我對它的open方法的封裝:使用進你可以忽略後面的三個參數,直接把一個SQL語句傳給它.
HRESULT CAdoRecordSet::Open(LPCTSTR strSQL,
long lOption,
CursorTypeEnum CursorType,
LockTypeEnum LockType)
{
try
{
if (m_pConnection == NULL)
{
return -1;
}
else if (m_pRecordset == NULL)
{
m_pRecordset.CreateInstance("ADODB.Recordset");
}
m_pRecordset->Open(_bstr_t(strSQL),
_variant_t((IDispatch*)m_pConnection->GetConnection(), true),
CursorType, LockType, lOption);
if (m_pRecordset == NULL)
{
return -1;
}
return (m_pRecordset->adoEOF) ? 0 : 1;
}
catch (_com_error e)
{
TRACE(_T(":( 打開記錄集發生錯誤: %s\n"), e.ErrorMessage());
return -1;
}
}
例如我們可以這樣來用:CAdoRecordSet rset;
rset.SetAdoConnection(&(GetDocument()->m_adoConnection));//記得要先指定相應的連接對象,否則會出錯.
m_strSQL = "select * from city";//要執行的SQL語句.
rset.Open(m_strSQL);
七.寫一個數據查詢工具(我對實現過程只稍作了介紹,具體內容請參考源代碼):
7.1 連接數據庫
首先要編寫連接到數據庫的代碼,為此,我寫了一個對話框類(CLogoDig)用來選擇不同的數據源,
然後在視圖類(這個視圖類是從CFromView類派生的)添加 CAdoConnection 類成員變量,並添加如下連接函數
void CAccessView::OnFileConnect()
{
CLogoDig dlg;
if (dlg.DoModal() == IDOK)
{
if (dlg.m_nSrcType == 0)
{
CString strConnect = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + dlg.m_strSrcName;
GetDocument()->m_adoConnection.Disconnect();
if (!GetDocument()->m_adoConnection.Connect(LPCSTR(strConnect)))
{
AfxMessageBox("連接數據庫失敗!");
return;
}
}
else if (dlg.m_nSrcType == 1)
{
CString strConnect = "Provider=SQLOLEDB.1;Data Source=" + dlg.m_strSrcName +
";Initial Catalog=" + dlg.m_strDbName +
";User ID=" + dlg.m_strUserName + "; PWD=" + dlg.m_strPassWord;
GetDocument()->m_adoConnection.Disconnect();
if (!GetDocument()->m_adoConnection.Connect(LPCSTR(strConnect)))
{
AfxMessageBox("連接數據庫失敗!");
return;
}
}
((CMainFrame*)GetParentFrame())->m_wndLeftBar.InitTree();
}
}
7.2 CCoolControlBar類和CMSFlexGrid類
在這個數據查詢工具中我們使用了另外兩個類:CCoolControlBar類和CMSFlexGrid類。.前者是我寫的一個可以動態改變大小的控制條類,後者是系統自帶一個網格控件,這個控件功能較少,但對於只用來顯示一下查詢結果已經夠用了。
在編輯CFromView類對話框資源視圖中,在正在編輯的對話框資源上點右鍵,選擇插入ActiveX控件,然後選擇"Microsoft FlexGrid control"控件。然後在類向導中在"Member Variables"頁中為它添加變量,類向導會提示要引入向個頭文件,確認,這時你的類視圖中就會增加好幾個類。
先介紹一個要用到的幾個函數:
SetCols 設置總共擁有的列數
SetFixedCols 設置固定的列數,即背景為灰色的那種
SetRows 設置總共擁有的行數
SetCol 設置當前列
SetRow 設置當前行
SetText 設置當前格的文本。位置由上面兩個函數決定。
SetColWidth 設置列寬
7.3 數據的顯示與處理
另外我們還需要兩個編輯控件,用來輸入SQL語句和顯示錯誤信息.並在OnSize消息處理函數中動態設置它們的位置:
void CAccessView::OnSize(UINT nType, int cx, int cy)
{
CFormView::OnSize(nType, cx, cy);
if (m_wndGrid.GetSafeHwnd() != NULL) //控件是否已經創建
{
m_editError.MoveWindow(0, 10, cx, cy - 50);
m_wndGrid.MoveWindow(0, 0, cx, cy - 40);
m_editSQL.MoveWindow(0, cy - 40, cx, 40);
}
}
添加一條菜單項並添加相應響應函數,用於開始執行輸入的SQL語句:
void CAccessView::OnRun()
{
UpdateData();
UpdateGrid();
}
根據查詢情況顯示查詢結果:
void CAccessView::UpdateGrid()
{
//連接對象是否打開------------------------------------------
if (!GetDocument()->m_adoConnection.IsOpen())
{
AfxMessageBox("數據庫沒有打開或已經關閉!");
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塊,以防萬一,:(
try
{
//取得記錄集的字段數和行數----------------------------------
int nrow = rset.GetRecordCount();
int ncol = rset.GetFields()->Count;
//設置網格控件的列數和行數----------------------------------
m_wndGrid.SetCols(ncol);
m_wndGrid.SetRows(nrow + 1); // 多留一行以顯示字段名
m_wndGrid.SetFixedCols(0);
CString value;
//填充字段名-----------------------------------------------
m_wndGrid.SetRow(0);
for (int i = 0; i < ncol; i++)
{
m_wndGrid.SetCol(i);
m_wndGrid.SetText(LPCSTR(rset.GetFieldName(i)));
//設置當前列的大致寬度-------------------------------
int nwidth = rset.GetFieldDefineSize(i) * 200;
nwidth = nwidth > 2000 ? 2000 : nwidth;
m_wndGrid.SetColWidth(i, nwidth);
}
//讀取記錄集-----------------------------------------------
int n = 1;
while (!rset.IsEOF())
{
m_wndGrid.SetRow(n);
n++;
for (int i = 0; i < ncol; i++)
{
m_wndGrid.SetCol(i);
rset.GetValueString(value, (long)(i));
m_wndGrid.SetText(LPCTSTR(value));
}
rset.MoveNext();
}
m_wndGrid.ShowWindow(SW_SHOW);
}
catch (_com_error)
{
return;
}
}
記錄集用完後,可以及時用Close()將它關閉,以釋放相應的資源. CAdoRecordSet類折構函數,會自動關閉記錄.
7.4 其它功能(獲取數據庫信息)
我們還可以加一點另外的功能:在右邊的樹控件中顯示數據庫所擁有的表單和它們各自所擁有所有字段.這段主要是用來演示如何獲得數據庫的一些信息.
主要實現函數如下:
void CLeftBar::InitTree()
{
CAdoRecordSet rset;
_bstr_t Value;
CString strTablename = "";
HTREEITEM item = TVI_ROOT;
try
{
if (GetDocument()->m_adoConnection.GetConnection()->State != adStateOpen) return;
m_ctrlTree.DeleteAllItems();
//取得數據庫字段信息---------------------------------------------
rset = GetDocument()->m_adoConnection.OpenSchema (adSchemaColumns);
while (!rset.IsEOF())
{
CString strValue;
//取得表名-----------------------------------------------
rset.GetValueString(strValue, "TABLE_NAME");
if (strValue != strTablename)
{
strTablename = strValue;
item = m_ctrlTree.InsertItem((LPCTSTR)strTablename, 1, 1);
}
//取得字段名--------------------------------------------
Value = rset.GetFields()->Item[L"COLUMN_NAME"]->Value;
m_ctrlTree.InsertItem((LPCTSTR)Value, 2, 2, item);
rset.MoveNext();
}
}
catch(_com_error e)
{
}
}
當然,你一樣可以查詢看數據庫還擁有哪些視圖,索引等信息. 這裡還用到了CCoolControlBar類,但如何使用這裡就不細說了,畢竟現在主要談的是ADO,如果你對它有什麼興趣可以真接找我.:)
一個小查詢器就差不多完成了。
八、其他參考信息(有很多我在源代碼裡面已有詳細注釋,就不一一重復了)