MFC使用ADO操作数据库
1. ADO概述
ADO是Microsoft为最新和最强大的数据访问范例OLE DB而设计的,是一个便于使用的应用程序层接口。ADO使您能够编写应用程序以通过OLE. DB提供者访问和操作数据库服务器中的数据。ADO最主要的优点是易于使用、速度快、内存支出少和磁盘遗迹小。ADO在关键的应用方案中使用最少的网络流量,并且在前端和数据源之间使用最少的层数,所有这些都是为了提供轻量、高性能的接口。之所以称为ADO,是用了一个比较熟悉的暗喻,OLE自动化接口。
OLE DB是一组“组件对象模型”(COM)接口,是新的数据库低层接口,它封装了ODBC的功能,并以统一的方式访问存储在不同信息源中的数据。OLE DB是Microsoft UDA(Universal Data Access)策略的技术基础。OLE DB为任何数据源提供了高性能的访问,这些数据源包括关系和非关系数据库、电子邮件和文件系统、文本和图形、自定义业务对象等等。也就是说,OLE DB并不局限于ISAM、Jet甚至关系数据源,它能够处理任何类型的数据,而不考虑它们的格式和存储方法。在实际应用中,这种多样性意味着可以访问驻留在Excel 电子数据表、文本文件、电子邮件/目录服务甚至邮件服务器,诸如Microsoft Exchange中的数据。但是,OLE DB应用程序编程接口的目的是为各种应用程序提供最佳的功能,它并不符合简单化的要求。所需要的API应该是一座连接应用程序和OLE DB的桥梁,这就是 ActiveX Data Objects (ADO)。
2. 利用ADO操作总体思路
- 引入ADO库文件;
- 初始化OLE/COM库;
- 用Connection对象连接数据库;
- 利用建立好的连接,利用Recordset对象取得结果记录集进行查询、处理;
- 使用完毕后关闭连接释放对象。
3. 在VC++中使用ADO的步骤
1. 引入ADO库文件
使用ADO前必须在工程的stdafx.h头文件里用直接引入符号#import引入ADO库文件,以使编译器能正确编译。代码如下所示:
#import "c:\program files\common files\system\ado\msado15.dll" \no_namespaces \ rename("EOF" adoEOF")
其中路径名可以根据自己系统安装的ADO支持文件的路径来自行设定。当编译器遇到#import语句时,它会为引用组件类型库中的接口生成包装类,#import语句实际上相当于执行了API涵数LoadTypeLib()。#import语句会在工程可执行程序输出目录中产生两个文件,分别为*.tlh(类型库头文件)及*.tli(类型库实现文件),它们分别为每一个接口产生智能指针,并为各种接口方法、枚举类型,CLSID等进行声明,创建一系列包装方法。语句no_namespace说明ADO对象不使用命名空间,rename ("EOF", "adoEOF")说明将ADO中结束标志EOF改为adoEOF,以避免和其它库中命名相冲突。现在不需添加另外的头文件,就可以使用ADO接口了。
2. 初始化OLE/COM库环境
必须注意的是,ADO库是一组COM动态库,这意味应用程序在调用ADO前,必须初始化OLE/COM库环境。在MFC应用程序里,一个比较好的方法是在应用程序主类的InitInstance成员函数里初始化OLE/COM库环境。
BOOL CADODataBase1App::InitInstance()
{
AfxEnableControlContainer();
//初始化OLE DLLs
if (!AfxOleInit()) //这就是初始化COM库
{
AfxMessageBox("初始化OLE DLL失败!");
return FALSE;
}
}
3. 使用_ConnectionPtr接口
_ConnectionPtr主要是一个连接接口,取得与数据库的连接。它的连接字符串可以是自己直接写,也可以指向一个ODBC DSN,首先我们需要添加一个指向Connection对象的指针_ConnectionPtr m_pConnection。
_ConnectionPtr m_pConnection;//在头文件stdAfx.h建立连接对象指针
在ADO操作中建议语句中要常用try...catch()来捕获错误信息,因为它有时会经常出现一些意想不到的错误。
BOOL CADODataBase3Dlg::OnInitDialog()
{
CDialog::OnInitDialog();
…………(前面省略)
HRESULT hr;
try
{
hr = m_pConnection.CreateInstance("ADODB.Connection");//创建Connection对象
if(SUCCEEDED(hr))
{
hr = m_pConnection->Open("student","","",adModeUnknown);//连接数据库
}
}
catch(_com_error e) //捕捉异常
{
CString errormessage;
errormessage.Format("连数据库失败!\r\n错误信息:%s",e.ErrorMessage());
AfxMessageBox(errormessage); //显示错误信息
}
4. 使用_RecordsetPtr接口
_RecordsetPtr智能指针,可以用来打开库内数据表,并可以对表内的记录、字段等进行各种操作。首先,在头文件stdAfx.h中建立记录集对象m_pRecordset。
_RecordsetPtr m_pRecordset; //在头文件stdAfx.h中建立记录集对象
利用m_pRecordset对象取得结果记录集进行查询、处理前,同样使用try...catch()来捕获错误信息。
try
{
m_pRecordset->Open(_bstr_t(strSQL), m_pConnection.GetInterfacePtr(),adOpenDynamic,adLockOptimistic,adCmdText);
} //从数据库中打开表
catch (_com_error e)
{
CString strError;
strError.Format("警告:打开数据表异常。错误信息:%s",e.ErrorMessage());
AfxMessageBox(strError);
return;
}
记录集的遍历、处理:
①获取记录集的记录数
_variant_t RecordsAffected;
m_pRecordset=m_pConnection->Execute("SELECT COUNT(*) FROM studentinfo",&RecordsAffected,adCmdText);
_variant_t vIndex = (long)0;
_variant_t vCount = m_pRecordset->GetCollect(vIndex); //取得第一个字段的值放入vCount变量
count=vCount.lVal;
②移到第一条记录
m_pRecordset->MoveFirst();
curNo=1;
m_Status.Format("共有%d条记录,当前第%d条",count,curNo);
UpdateData(false);
ShowRecord();//显示记录
③移到下一条记录
m_pRecordset->MoveNext();
curNo++;
if(m_pRecordset->adoEOF)
{
m_pRecordset->MoveLast();
}
m_Status.Format("共有%d条记录,当前第%d条",count,curNo);
UpdateData(false);
ShowRecord();//显示记录
④移到上一条记录
m_pRecordset->MovePrevious();
curNo--;
if(m_pRecordset->BOF)
{
m_pRecordset->MoveFirst();
}
m_Status.Format("共有%d条记录,当前第%d条",count,curNo);
UpdateData(false);
ShowRecord();//显示记录
⑤移到最后一条记录
m_pRecordset->MoveLast();
curNo=count;
m_Status.Format("共有%d条记录,当前第%d条",count,curNo);
UpdateData(false);
ShowRecord();//显示记录
⑥删除当前记录
void CADODataBase3Dlg::OnRemove()
{
// TODO: Add your control notification handler code here
m_pRecordset->Delete(adAffectCurrent);
OnRadio3(); //删除操作
}
⑦修改记录
m_pRecordset->PutCollect("stuNo",_variant_t(m_strNumber));
m_pRecordset->PutCollect("stuName",_variant_t(m_strName));
m_pRecordset->PutCollect("stuSex",_variant_t(m_strSex));
m_pRecordset->PutCollect("stuAddress",_variant_t(m_strAddress));
m_pRecordset->Update();//提交记录
m_Status="成功修改了一条记录!";
UpdateData(false);
⑧在编辑框中显示记录
void CADODataBase3Dlg::ShowRecord()
{
m_strNumber=(char*)_bstr_t(m_pRecordset->GetCollect("stuNo"));
m_strName=(char*)_bstr_t(m_pRecordset->GetCollect("stuName"));
m_strSex=(char*)_bstr_t(m_pRecordset->GetCollect("stuSex"));
m_strAddress=(char*)_bstr_t(m_pRecordset->GetCollect("stuAddress"));
UpdateData(false);
}
5. 关闭连接释放对象
记录集或连接都可以用Close()方法来关闭:
m_pRecordset->Close();//关闭记录集对象
m_pConnection->Close();//关闭连接对象
至此,利用ADO已经可以实现对数据库的操作,接下来就是对程序框架的完善。
4. 编程步骤
1. 启动Visual C++6.0,生成一个基于对话框的应用程序,将该程序命名为ADODataBase3;
2. 在对话框界面上放置显示记录列表控件和添加、删除记录用的的编辑、按钮控件,具体设置参加代码中对话框资源部分;
3. 使用Class Wizard为添加、修改数据库记录的按钮添加消息响应函数;
4. 添加成程序代码,编译运行程序。
5. 最终界面如下: