1、 新建MFC对话框
工程名取为ADO_Test。
2、 设计界面。
四个Button控件,2个Static控件,2个编辑框控件,1个ListBox控件。
3、 汇入ADO接口文件。
ADO的接口文件即msado15.dll。在StdAfx.h文件里汇入:
#import "msado15.dll" no_namespace rename ("EOF", "adoEOF")
这里采用相对路径,因此需要把msado15.dll文件拷贝到当前工程所在目录,这里即是:D:\wave12\C++工程师培训\Example\VC++\ADO_Test\ADO_Test。
#import语句会在工程可执行程序输出目录中产生两个文件,分别为*.tlh(类型库头文件)及*.tli(类型库实现文件),它们分别为每一个接口产生智能指针,并为各种接口方法、枚举类型,CLSID等进行声明,创建一系列包装方法。语句no_namespace说明ADO对象不使用命名空间,rename ("EOF", "adoEOF")说明将ADO中结束标志EOF改为adoEOF,以避免和其它库中命名相冲突。
4、 连接数据库
在对话框类头文件里声明一成员变量m_pConnection,它是连接数据库的智能指针对象。
_ConnectionPtr m_pConnection;
在对话框的OnInitDialog函数里连接数据库。
m_pConnection.CreateInstance(__uuidof(Connection));
5、 读取数据
_RecordsetPtr智能指针,可以用来打开数据库内的数据表,并可以对表内的记录、字段等进行各种操作。
在读取数据按钮的单击事件里进行读取数据操作。
void CADO_TestDlg::OnBnClickedRead()
{
// TODO: 在此添加控件通知处理程序代码
m_AccessList.ResetContent(); // 每次读取数据时都先清空界面上的旧数据
_RecordsetPtr pRecordset;
pRecordset.CreateInstance(__uuidof(Recordset));
try
{
pRecordset->Open("SELECT * FROM ws_Admin", // 查询DemoTable表中所有字段
m_pConnection.GetInterfacePtr(), // 获取库接库的IDispatch指针
adOpenDynamic,
adLockOptimistic,
adCmdText);
}
catch(_com_error *e)
{
AfxMessageBox(e->ErrorMessage());
}
_variant_t var;
CString strName,strAge;
try
{
if(!pRecordset->BOF)
pRecordset->MoveFirst();
else
{
AfxMessageBox(L"表内数据为空");
}
// 读入库中各字段并加入列表框中
while(!pRecordset->adoEOF)
{
var = pRecordset->GetCollect("Acount");
if(var.vt != VT_NULL)
strName = (LPCSTR)_bstr_t(var);
var = pRecordset->GetCollect("Pwd");
if(var.vt != VT_NULL)
strAge = (LPCSTR)_bstr_t(var);
m_AccessList.AddString( strName + " --> "+strAge );
pRecordset->MoveNext();
}
pRecordset->Close();
pRecordset = NULL;
}
catch(_com_error *e)
{
AfxMessageBox(e->ErrorMessage());
}
}
pRecordset这里作为函数内部的局部对象,这样做的目的是函数执行完后更加方便的清理该对象,它不会与其他按钮操作里的Recordset对象冲突。清理Recordset对象就是调用Close方法,并将它设置为NULL。
6、 新增记录
利用Recordset对象的Open方法打开数据集,然后利用AddNew方法增加新记录,最后使用Update方法更新到数据库的数据表里。
void CADO_TestDlg::OnBnClickedAdd()
{
// TODO: 在此添加控件通知处理程序代码
_RecordsetPtr pRecordset;
pRecordset.CreateInstance(__uuidof(Recordset));
try
{
pRecordset->Open("SELECT * FROM ws_Admin", // 查询DemoTable表中所有字段
m_pConnection.GetInterfacePtr(), // 获取库接库的IDispatch指针
adOpenDynamic,
adLockOptimistic,
adCmdText);
}
catch(_com_error *e)
{
AfxMessageBox(e->ErrorMessage());
}
try
{
UpdateData(TRUE);
// 写入各字段值
pRecordset->AddNew();
pRecordset->PutCollect("Acount", _variant_t(m_strAcount));
pRecordset->PutCollect("Pwd", _variant_t(m_strPwd));
pRecordset->Update();
pRecordset->Close();
pRecordset = NULL;
m_strAcount = "";
m_strPwd = "";
UpdateData(FALSE);
OnBnClickedRead();
int iCount = m_AccessList.GetCount();
m_AccessList.SetCurSel(iCount - 1);
}
catch(_com_error *e)
{
AfxMessageBox(e->ErrorMessage());
}
}
7、 修改记录
修改记录和新增记录类似,也是先利用Open打开数据集,然后利用Move方法移动到要修改的记录位置处,然后进行数据修改,最后调用Update方法更新的数据库。
void CADO_TestDlg::OnBnClickedMod()
{
// TODO: 在此添加控件通知处理程序代码
_RecordsetPtr pRecordset;
pRecordset.CreateInstance(__uuidof(Recordset));
try
{
pRecordset->Open("SELECT * FROM ws_Admin", // 查询DemoTable表中所有字段
m_pConnection.GetInterfacePtr(), // 获取库接库的IDispatch指针
adOpenDynamic,
adLockOptimistic,
adCmdText);
}
catch(_com_error *e)
{
AfxMessageBox(e->ErrorMessage());
}
try
{
int curSel = m_AccessList.GetCurSel();
if (curSel == -1)
{
pRecordset->Close();
pRecordset = NULL;
return;
}
UpdateData(TRUE);
// 先将指针移向第一条记录,然后就可以相对第一条记录来随意移动记录指针
pRecordset->MoveFirst();
pRecordset->Move(long(curSel));
pRecordset->PutCollect("Acount", _variant_t(m_strAcount));
pRecordset->PutCollect("Pwd", _variant_t(m_strPwd));
pRecordset->Update();
pRecordset->Close();
pRecordset = NULL;
OnBnClickedRead();
m_AccessList.SetCurSel(curSel);
}
catch(_com_error *e)
{
AfxMessageBox(e->ErrorMessage());
}
}
修改一条记录后,调用OnBnClickedRead函数,重新读取新的数据展现到界面上。
8、 删除记录
删除数据最方便的就是利用Connection对象的Execute方法,它可以执行各种有效的SQL语句。
void CADO_TestDlg::OnBnClickedDel()
{
// TODO: 在此添加控件通知处理程序代码
try
{
int curSel = m_AccessList.GetCurSel();
if (curSel == -1)
{
return;
}
CString strText;
m_AccessList.GetText(curSel, strText);
int iPos = strText.Find(L" --> ");
CString strAcount = strText.Mid(0, iPos);
CString strSql;
strSql.Format(L"DELETE FROM ws_Admin WHERE Acount='%s'", strAcount);
m_pConnection->Execute((_bstr_t)strSql, NULL, adCmdText);
}
catch(_com_error *e)
{
AfxMessageBox(e->ErrorMessage());
}
OnBnClickedRead();
}
实际上,新增数据和修改数据,也可以利用insert和update语句把sql构造好,然后利用Connection对象的Execute方法。很显然,相比Open方法,然后再调用Update更为简洁,代码可读性也更强。
9、 运行结果
评论