《MFC用ADO读写Access数据库实例》.docx
- 文档编号:13773652
- 上传时间:2023-06-17
- 格式:DOCX
- 页数:25
- 大小:26.94KB
《MFC用ADO读写Access数据库实例》.docx
《《MFC用ADO读写Access数据库实例》.docx》由会员分享,可在线阅读,更多相关《《MFC用ADO读写Access数据库实例》.docx(25页珍藏版)》请在冰点文库上搜索。
《MFC用ADO读写Access数据库实例》
MFC使用ADO读写Access数据库实例
ADO(ActiveXDataObject)是Microsoft数据库应用程序开发的新接口,是建立在OLEDB之上的高层数据库访问技术,即使你对OLEDB,COM不了解也能轻松对ADO,因为它非常简单易用,甚至比你以往所接触的ODBCAPkDAO、RDO都要容易使用,并不失灵沽性。
本文详细地介绍在VisualC++开发环境卜如何使用ADO来进行数据库应用,宇开发,并给出示例代码。
为了使读者朋友都能测试本例提供的代码,我们采用Access数据库,您可以直接在我们提供的示例代码中找到这个test.mdb
一、实现方法
万事开头难,任何一种新技术对于初学者来说最重要的还是”入门”,掌握其要点。
让我们来看看ADO数据库开发的基本流程吧!
它的基本步骤如下:
(1)初始化COM库,引入ADO库定义文件
(2)用Connection对象连接数据库
(3)利用建立好的连接,通过Connection、Command对象执行SQL命令,或利用Recordset对象取得结果记录集进行查询、处理。
(4)使用完毕后关闭连接释放对象。
下面我们将详细介绍上述步骤并给出相关代码。
1、COM库的初始化
我们可以使用AfxOlelnitQ来初始化COM库,这项工作通常在CWinApp:
:
!
2、用import指令引入ADO类型库
为了引入ADO类型库,需要在项目的stdafx.h文件中加入如卜语句:
#importwcAprogramfiles\commonfiles\system\ado\msado15.dll"no^namespacerenameCEOF^/adoEOF")
这一语句有何作用呢?
其最终作用同我们己经十分熟悉的include类似,编译的时候系统会为我们生成msado15.tlh.ado15.tli两个C++头文件来定义AD。
库。
需要读者朋友注意的是:
您的开发环境中msado15.dll不一定在这个目录下,请按实际情况修改;在编译的时候可能会出现如下警告,对此微软在MSDN中作了说明,并建议我们不要理会这个警告:
msado15.tlh(405):
warningC4146:
unaryminusoperatorappliedtounsignedtype,resultstillunsigned。
3、创建Connection对象并连接数据库
为了首先我们需要添加一个指向Connection对象的指针_ConnectionPtrm_pConnect
ion,卜.面的代码演示了如何创建Connection对象实例及如何连接数据库并进行异常捕捉:
BOOLCADOTestlDlg:
:
OnlnitDialog()
{
CDialog:
:
OnlnitDialog();
HRESULThr;
try
(
hr=m_pConnection.CreatelnstancerADODB.ConnectiorT);〃/创建Connection对象
if(SUCCEEDED(hr))
{
hr=m_pConnection->Open(*Provider=Microsoft.Jet.OLEDB40.
DataSource=testmdb^^/^adModellnknown);///连接数据库
〃上面一句中连接字串中的Provider足针对ACCESS2000环境的,对丁・ACCESS97-
〃需要改为:
Provider二Micros。
化JetOLEDB351;
)
}
catch(_com_errore)/〃捕捉异常
(
CStnngerrormessage;
errormessage.Format("连接数据库失败!
\r\n错误信M:
%sM,eErrorMessage());
AfxMessageBox(errormessage);///B示错误信息
}
在这段代码中我们是通过Connection对象的Open方法来进行连接数据库的,下而是
该方法的原型:
HRESULTConnection15:
:
Open(_bstr_tConnectionstring,_bstr_tUserID,_bstr_tPassword,longOptions):
上述函数中参数ConnectionStnng连接字串;参数UserID是用户名;参数Passwo
一般情况下0ptions可以是如下几个常景:
adModeUnknown:
缺省。
当前的许可权未设置
adModeRead:
只读
adModeWrite只写
adModeReadWrite:
nf以读写
adModeShareDenyRead:
阻止其它Connection对象以读权限打开连接
adModeShareDenyWrite:
阻止其它Connection对象以写权限打开连接
adModeShareExclusive:
阻止其它Connection对象以读写权限打开连接
adModeShareDenyNone:
阻止其它Connection对象以任何权限打开连接
我们绐出一些常用的连接方式供大家参考:
(1)通过JET数据库引擎对ACCESS2000数据库的连接:
m_pConnection・>Open「Provider二Microsoft.JetOLEDB40;
DataSource二C:
\test.mdW\adModeUnknown);
(2)通过DSN数据源对任何支持ODBC的数据库进行连接:
m_pConnection->Open("DataSource=adotest7UID=sa;PWD=?
\"\,,B,adModeUnknown);
(3)不通过DSN对SQLSERVER数据摩进行连接:
m_pConnection->Open(*driver=(SQLServer};Server=127001;DATABASE=vckbase;
UID=sa,PWD=139\"\"\adModeUnknown);
其中Server是SQL服务器的名称,DATABASE是库的名称。
Connection对象除Open()方法外还有许多方法,我们先介绍Connection对象中两
个有用的属性ConnectionTimeOut与StateoConnectionTimeOut用来设置连接的超时时
间,需要在Open之前调用,例如:
m_pConnection->ConnectionTimeout=5;///设置超时时间为5秒
m_pConnection->Open(BDataSource二adotest二"「LadModeUnknown);
State属性指明当前Connection对象的状态,0表示关闭,1表示己经打开,我们可以
通过读取这个属性来作相应的处理,例如:
if(m_pConnection->State)
m-PConnection->Close();〃/如果己经打开『连接则关闭它
4、执行SQL命令并取得结果记录集
为了取得结果记录集,我们定义一个指向Recordset对象的指针」RecordsetPtrm_pRecordset;
并为其创建Recordset对象的实例:
m_pRecordset.Createlnstance(HADODBRecordset"),SQL命令的执行可以采用多种形式,卜•而我们一一进行阐述。
(1)利用Connection对象的Execute方法执行SQL命令
Execute()方法的原型如卜所示:
RecordsetPtrConnection15:
:
Execute(bstrtCommandText,VARIANT*RecordsAffected,longOptions)
其中CommandText是命令字串,通常是SQL命令。
参数RecordsAffected是操作完成后所影响的行数,参数0ptions表示CommandText中内容的类型,Options可以取如F值之一:
adCmdText表明CommandText是文本命令;adCmdTable表明CommandText是一个表名;adCmdProc表明CommandText是一个存储过程;adCmdUnknown表明CommandText内容未知。
Execute()函数执行完后返回一个指向记录集的指针,下面我们给出具体代码并作说明:
varianttRecordsAffected;
〃/执行SQL命令:
CREATETABLE创建表格users.users包含四个字段:
整形ID,字符串username,^形old,日期型birthday
m_pConnection・>Execute「CREATETABLEusers(IDINTEGER.username
TEXT,oldINTEGER:
birthdayDATETIME)\&RecordsAfected,adCmdText);
///往表格里而添加记录
m_pConnection->Execute(-INSERTINTOusers(IDusername,old,birthday)
VALUES(1,Washington^S/l970/1/1y.&RecordsAffected.adCmdText);
〃/将所有记录old字段的值加一
m^pConnection^ExecuteCUPDATEusersSETold=old*r:
&RecordsAffected,adCmdText);
〃/执行SQL统计命令得到包含记录条数的记录集
m^pRecordset=m_pConnection->ExecuteCSELECTCOUNT(*)FROM
usersHr&RecordsAffected,adCmdText),
_vanant_tvlndex=(long)0.
^variant_tvCount=m_pRecordset->GetCollect(vlndex);///取得第一个字段的值放入vCount变
景
m_pRecordset->Close();///关闭记录集
CStnngmessage,
messageFormat("共Tf%d条记录\vCountIVal);
AfxMessageBox(message);///显示当前记录条数
(2)利用Command对象来执行SQL命令
_CommandPtrm_pCommand;
m_pCommand.CreatelnstanceCADODB.Command");
_vanant_tvNULL;
vNULL.vt=VT_ERROR
vNULL.scode=DISP_E_PARAMNOTFOUND;〃/定义为无参数
m_pCommand->ActiveConnection=m_pConnection;///非常关键的一句・将建立的连接质伉给它
m_pCommand->CommandText="SELECT1FROMusers11;///命令字串
m_pRecordset=m_pCommand->Execute(&vNULL,&vNULLtadCmdText),
〃执行命令取得记录集
在这段代码中我们只是用Command对象来执行了SELECT查询语句,Command对
象在进行存储过程的调用中能真正体现它的作用。
卜次我们将详细介绍。
(3)直接用Recordset对象进行查询取得记录集,例如:
m_pRecordset->Open("SELECT*FROMusers",_variant_t((lDispatch*)m_pConnectionttrue)fadOpenStatic.adLockOptimistic.adCmdText);
Open()方法的原型如下:
HRESULTRecordset15:
Open(const^vanantj&Source,const^variantj&ActiveConnection.enumCursorTypeEnumCursorType,enumLockTypeEnumLockType,longOptions)
上述函数中参数Source是数据查询字符串:
参数ActiveConnection是己经建立好的连接(我们需要用Connection对象指针来构造一个_vsnant_t对象):
参数CursorType光标类型,它可以是以下值之一:
请看这个枚举结构:
enumCursorTypeEnum
{
adOpenllnspecified=-1,/〃不作特别指定
adOpenForwardOnly=0;//前滚静态光标。
这种光标只能向前浏览记录集,比如用MoveNext向前滚动,这种方式可以提高浏览速度。
但诸如
BookMark,RecordCounttAbsolutePosition,AbsolutePage都不能使用
adOpenKeyset=1///采用这种光标的记录集看不到其它用户的新增、删除操作.但对丁•更新原有记录的操作对你是可见的.
adOpenDynamic=2,///动态光标。
所有数据库的操作部会立即在务用户记录集上反应出来。
adOpenStatic=3///^态光标。
它为你的记泉集产生一个静态备份,但其它用户的新增、删除、更新操作对你的记录集来说是不可见的。
参数LockType表示数据库的锁定类型,它可以是以下值之一,请看如下枚举结构:
enumLockTypeEnum
adLockUnspecified=-1未指定
adLockReadOnly=1,///只读记录集
adLockPessimistic=2,^观锁定方式。
数据在更新时锁定其它所有动作,这是最安全的锁定机制
adLockOptimstic=3.乐观锁定方式.只有在你调用Update方法时才锁定记录.在此之前仍然可以做数据的更新、插入、删除等动作
adLockBatchOptimistic=4,乐观分批更新。
编辑时正录不会锁定,更改、插入及删除是在批处理模式下完成。
参数0ptions的含义请参考本文中对Connection对象的Execute()方法的介绍.
5、记录集的遍历、更新
根据我们刚才通过执行SQL命令建立好的users表,它包含四个字段ID,username.old:
birthday
以下的代码实现:
打开记录集,遍历所有记录,删除第一条记录,添加三条记录,移动光标到第二条记录,更改其年龄数据,保存到数据库。
_vanant_tvUsernamevBirthday^DyOld;
_RecordsetPtrm_pRecordset;
m_pRecordset.Createlnstance(*ADODBRecordset*);
m_pRecordset->Open("SELECT*FROMusers\_vanantJ((IDispatch*)m_pConnection1true),
adOpenStatic.adLockOptimistic^dCmdText):
while(!
m_pRecordset->adoEOF)
〃/这里为什么是adoEOF而不地EOF昵?
还记得rename("EOF.肖doEOF")这一句吗?
{
vID=m_pRecordset->GetCollectLvariantJ((long)0));///取得第1列的值,从0开始计数.你
也可以直接给出列的名称:
vUsername=m_pRecordset->GetCollect("usernamee);///l|Xf^username字段的值
vOld=m_pRecordset->GetCollect("oldM);
vBirthday=m_pRecordset->GetCollect("birthday");
///在DEBUG方式下的OUTPUT窗口输出记录集中的记录
if(vlD.vtl=VT_NULL&&vUsernamevt!
=VT_NULL&&vOld.vt!
=VT_NULL&&
vBirthday.vt!
=VT_NULL)
TRACE「id:
%d,姓名:
%s,年龄:
%d,生
ri:
%s\r\nM,vlD.IVal,(LPCTSTR)LbstrJ)vUsername,vOld.lVal)(LPCTSTR)LbstrJ)vBirthday);
m_pRecordset->MoveNext();///移到下一条记录
m_pRecordset->MoveFirst();///移到首条记录
m_pRecordset->Delete(adAffectCurrent);///删除当前记录
〃/添加三条新记录并赋值
for(jnti=0;i<3;i++)
{
m_pRecordset->AddNew();///添加新记录
m_pRecordset->PutCollect(*ID"l-variant_t((long)(i+10)));
m_pRecordset->PutCollect(,,usemame,\_variant_tC叶利钦,));
m_pRecordset->PutCollect("old,,,_variant_t((long)71));
m_pRecordset->PutCollectCbirthday',._variantJ(M930-3-15"));
}"
m_pRecordset->Move(1._vanant_t((long)adBookmarkFirst))///从第一条记京往卜移动一条记录,即移动到第二条记录处
m_pRecordset・>PutCollect(_variant_trold)_variant_t((long}45));///修改其年龄
m_pRecordset->Update();///保存到库中
6、关闭记录集与连接
记录集或连接都可以用Close()方法来关闭:
m_pRecordset->Close();///关闭记录集
m_pConnection->Close();///关闭连接
至此,我想读者朋友己经熟悉了ADO操作数据库的大致流程,也许您己经胸有成竹,也许您还有点胡涂,不要紧!
建议你尝试写几个例子,这样会更好地熟悉ADO,最后我给大家写了个小例了,例了实现的功能是读出所有记录并放到列表控件中,同时可以添加、删除、修改记录。
二、编程步骤
1、启动VisualC++6.0,生成一个基于•对话框的应用程序,将该程序命名为ADOTest1:
2、在对话框界面上放置显示记录列表控件和添加、删除记录用的的编辑、按钮控件,
其体设置参加代码中对话框资源部分;
3、使用ClassWizard为添加、修改数据库记录的按钮添加消息响应函数:
4、添加成程序代码,编译运行程序。
三、程序代码
/////〃///〃////////〃〃/////////////〃〃/〃〃〃///ADOTestlDig.h:
headerfile
#if!
defmed(AFXADOTEST1DLGH29B385C002C04588A8B4D0EFBB4F578DINCLUDED)
#defmeAFX_ADOTEST1DLG_H_29B385C0_02C0_4588_A8B4_D0EFBB4F578D_INCLUDED_
#if_MSC_VER>1000
#pragmaonce
#endif//_MSC_VER>1000
classCADOTestIDIg:
publicCDialog
{
IIConstruction
public:
BOOLm_bAutoSave;
voidSaveData();
voidLoadData();
_vanant_tvllserlDyUsemameyOld^Birthday,
BOOLmbSuccess;
intm^nCurrentSel;
_RecordsetPtrm_pRecordset;
CADOTestlDlg(CWnd*pParent=NULL);//standardconstructor
//DialogData
〃{{AFX_DATA(CADOTest1Dig)
enum(IDD=IDD.ADOTEST1^DIALOG};
CButtonm_cDelltem7
CButtonmcAddltem;
CListCtrlmuserlist;
UINTm^nllserlD;
UINTm_nOld;
CStnngm_sUsername;
COIeDateTimemjBirthday;
//}}AFX_DATA
//ClassWizardgeneratedvirtualfunctionoverrides
〃{{AFX_VIRTUAL(CAD0Test1Dig)
protected:
virtualvoidDoDataExchange(CDataExchange*pDX);//DDX/DDVsupport
//}}AFX_VIRTUAL
//Implementation
protected:
HICONm_hlcon;
IfGeneratedmessagemapfunctions
〃{{AFX.MSG(CADOTest1Dig)
virtualBOOLOnlmtDialog();
afx_msgvoidOnSysCommand(UINTnlD?
LPARAMIParam);
afx_msgvoidOnPaint();
afx.msgHCURSOROnQueryDraglcon();
virtualvoidOnOK();
afx_msgvoidOnAdditem();
afx_msgvoidOnDelitem();
afx_msgvoidOnltemchangedllserlist(NMHDR*pNMHDR.LRESULT*pResult);
奶afx_msg
DECLARE_MESSAGE_MAP()
};
#endif
〃//〃〃/////〃//〃/〃//////////〃//〃/〃///〃//////〃ADOTestIDIg.cpp:
implementationfile
include"stdafxh"
includeHADOTest1h"
includeHADOTest1Dlg.h*
#ifdef_DEBUG
#definenewDEBUG_NEW
#undefTHIS_FILE
staticcharTHIS_FILEQ=_FILE_;
#endif
externCADOTestlApptheApp;
classCAboutDIg:
publicCDialog
{
public:
CAboutDlg();
IID
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- MFC用ADO读写Access数据库实例 MFC ADO 读写 Access 数据库 实例
![提示](https://static.bingdoc.com/images/bang_tan.gif)