分类: 数据库开发技术
2008-03-14 10:45:44
#import "c:\program files\common files\system\ado\msado15.dll" no_namespace rename("EOF","adoEOF")根据机器安装时候的设置不同具体的路径可能不一样。
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);七.写一个数据查询工具(我对实现过程只稍作了介绍,具体内容请参考源代码):
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(); } }
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类折构函数,会自动关闭记录.
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,如果你对它有什么兴趣可以真接找我.:)