分类: 数据库开发技术
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,如果你对它有什么兴趣可以真接找我.:)