1、第十二:ADO编程技术学习目的n ADO编程技术简介n ADO对象构造n 使用ADO控件访问数据n 使用ADO对象访问数据ADO编程技术简介三种数据库数据库访问技术简介:n ODBC(Open Database Connectivity,开放式数据库连接),是一种用来在有关或不有关数据库管理系统(DBMS)中存取数据原则应用程序接口(API)。n DAO(Data Access Object )即数据访问对象集,是Microsoft提供基于一种数据库对象集合访问技术。和ODBC同样,她们都是Windows API一某些,可以独立于(DBMS)进行数据库访问。DAO跟ODBC区别是:访问机制不同
2、!ODBC工作依赖于数据库制造商提供驱动程序。使用ODBC API时候,WindowsODBC管理程序,把对数据库访问祈求传递给对的驱动程序,驱动程序再使用SQL语句批示DBMS完毕数据库访问工作。ADO则绕开中心环节,直接使用数据库引擎(Microsoft Jet Database Engine)提供数据库访问对象集进行工作。速度比ODBC快。n ADO(ActiveX Data Object)是Microsoft数据库应用程序开发新接口,是建立在OLE DB之上高层数据库访问技术,提供了简朴易用访问各种数据资源(涉及关系型和非关系型)。是相对比较新数据库访问技术。ADO是Microsoft
3、数据库应用程序开发新接口,是建立在OLE DB之上高层数据库访问技术,请不必为此紧张,虽然你对OLE DB,COM不理解也能轻松对付ADO,由于它非常简朴易用,甚至比你以往所接触ODBC API、DAO、RDO都要容易使用,并不失灵活性。本文将详细地简介在VC下如何使用ADO来进行数据库应用程序开发。ADO对象构造ADO是一种面向对象组件库,用ADO访问数据库,其实就是运用ADO对象来操作数据如数据,因此咱们一方面要撑握ADO对象n 连接对象(connection):连接用于与数据库建立连接,执行查询及进行事务解决。在连接时必要要指定使用何种数据库OLEDB供应者n 命令对象(Command)
4、:可以执行数据库操作命令(如查询,修改,增长和删除)。用命令对象执行一种查询字串,可以返回一种记录集合。n 记录集对象(Recordset):用于表达查询返回成果集,它可以在成果集中增长,删除,修改和移动刻录。当建立一种记录集时,一种游标就自动建立了,查询所产生记录就放在本地游标中,游标有四种类型:仅能向前移动游标,静态游标,键集游标和动态游标。记录集对象是对数据库进行查询和修改重要对象。n 字段对象(Fields字段集合对象,Field字段对象):字段对象用于表达数据库或记录集中信息,涉及列值等信息。一种记录集或一种数据库中表涉及了多行记录,若将其当做二维网格,字段将是网格中列,每个字段分别
5、有名称,数据类型和值等属性,字段中涉及了来自数据库源中真实数据。要修改其中数据可在集录集修改Filed字段对象,也可以通过在刻录集中访问Fields字段集合对象,再定位要修改Filed字段对象。对记录集修改将最后被传送给数据库。n 参数对象(Parameter):是和命令对象联用一种对象。当命令对象执行查询是一种有参数查询时,就要用参数对象来为命令对象提供参数信息和数据。使用ADO访问数据库有两种方式:u 通过ADO控件访问数据库u 通过ADO对象访问数据库下面咱们将详细讲述这两种访问数据库办法。使用ADO控件访问数据库Access 是Microsoft Office中一种组件,是一种小型桌面
6、数据系统,咱们将以它为例子,解说使用ADO控件访问数据库办法。n 在Access 建立空数据库(参见Access 操作信息)n 在空数据库中建立一种名称为test一种表(参见Access 操作信息)n 建立一种VC基于对话框程序框架(也可以是其他向导建立手框架)n 在对话框界面编辑器中增长一种ADO控件。ADO控件有各种类型:u ADO Data连接控件,用于以便建立数据连接u ADO Grid控件,用于表达一种记录成果集在对话框编辑器,右键菜单中选取Insert ActiveX Control,在浮现对话框中选取Microsoft ADO Data Control,Version 6.0,点
7、OK即可以将连接控件加入到对话框中,同样办法选取Microsoft ADO Grid Control,Version 6.0加入到对话框中。n 设立对话框中连接控件属性上述两个控件属性设立和VC中其他控件设立是同样。连接控件属性设立:在属性对话框中选取Control页面,选取Use Connection String选项,点Build按钮,在浮现对话框中选取Microsoft Jet 4.0 OLEDB Provider提供者。点下一步选取刚建立Access 数据文献名称。点测试连接应能连接数据库通过。再一次打开连接控件属性设立,选取RecordeSource页面,在Command Type中
8、选取2-adCmdTable,在Table Or StoredProcedure Name中选取刚建立test表。到此完毕一连接控件设立。n 设立对话框中Grid控件属性同样办法打开Grid控件属性对话框。选取Control页面,选中Allow AddNew和Allow Delete复选框,再选取All页面,设立DataSource参数为连接控件IDn 运营该程序将可以在对话框中连接数据库,并取出表中数据显示在Grid控件中。使用ADO对象访问数据库ADO数据库开发基本流程n 初始化COM库,引入ADO库定义文献n 用Connection对象连接数据库n 运用建立好连接,通过Connectio
9、n、Command对象执行SQL命令,或运用Recordset对象获得成果记录集进行查询、解决。n 使用完毕后关闭连接释放对象。咱们采用Access数据库,您也可以直接在咱们提供示例代码中找到这个test.mdb。下面咱们将详细简介上述环节并给出有关代码。COM库初始化咱们可以使用AfxOleInit()来初始化COM库,这项工作普通在CWinApp:InitInstance()重载函数中完毕,请看如下代码:BOOL CADOTest1App:InitInstance() AfxOleInit();.用#import指令引入ADO类型库咱们在stdafx.h中加入如下语句:(stdafx.h这
10、个文献哪里可以找到?你可以在FileView中Header Files里找到)#import c:program filescommon filessystemadomsado15.dll no_namespace rename(EOF,adoEOF) 这一语句有何作用呢?其最后作用同咱们熟悉#include类似,编译时候系统会为咱们生成msado15.tlh,ado15.tli两个C+头文献来定义ADO库。几点阐明:n 您环境中msado15.dll不一定在这个目录下,请按实际状况修改n 在编译时候肯能会浮现如下警告,对此微软在MSDN中作了阐明,并建议咱们不要理睬这个警告。msado15.
11、tlh(405) :warning C4146:unary minus operator applied to unsigned type,result still unsigned创立Connection对象并连接数据库一方面咱们需要添加一种指向Connection对象指针:_ConnectionPtr m_pConnection;下面代码演示了如何创立Connection对象实例及如何连接数据库并进行异常捕获。BOOL CADOTest1Dlg:OnInitDialog()CDialog:OnInitDialog();HRESULT hr;try hr = m_pConnection.Cr
12、eateInstance(ADODB.Connection);/创立Connection对象if(SUCCEEDED(hr) hr = m_pConnection-Open(Provider=Microsoft.Jet.OLEDB.4.0;Data Source=test.mdb,adModeUnknown);/连接数据库 /上面一句中连接字串中Provider是针对ACCESS环境,对于ACCESS97,需要改为:Provider=Microsoft.Jet.OLEDB.3.51;catch(_com_error e)/捕获异常 CString errormessage;errormessa
13、ge.Format(连接数据库失败!r错误信息:%s,e.ErrorMessage();AfxMessageBox(errormessage);/显示错误信息 在这段代码中咱们是通过Connection对象Open办法来进行连接数据库,下面是该办法原型HRESULT Connection:Open(_bstr_t ConnectionString,_bstr_t UserID,_bstr_t Password,long Options )其中ConnectionString为连接字串,UserID是顾客名,Password是登录密码,Options是连接选项,用于指定Connection对象对
14、数据更新允许权,Options可以是如下几种常量:n adModeUnknown:缺省。当前允许权未设立n adModeRead:只读n adModeWrite:只写n adModeReadWrite:可以读写n adModeShareDenyRead:制止其他Connection对象以读权限打开连接n adModeShareDenyWrite:制止其他Connection对象以写权限打开连接n adModeShareExclusive:制止其他Connection对象打开连接n adModeShareDenyNone:容许其他程序或对象以任何权限建立连接。咱们给出某些惯用连接方式供人们参照:
15、n 通过JET数据库引擎对ACCESS数据库连接m_pConnection-Open(Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:test.mdb,adModeUnknown);n 通过DSN数据源对任何支持ODBC数据库进行连接:m_pConnection-Open(Data Source=adotest;UID=sa;PWD=;,adModeUnknown);n 不通过DSN对SQL SERVER数据库进行连接: m_pConnection-Open(driver=SQLServer;Server=127.0.0.1;DATABASE=vc
16、kbase;UID=sa;PWD=139,adModeUnknown);其中Server是SQL服务器名称,DATABASE是库名称Connection对象除Open办法外尚有许多办法,咱们先简介Connection对象中两个有用属性ConnectionTimeOut与State ConnectionTimeOut用来设立连接超时时间,需要在Open之前调用,例如:m_pConnection-ConnectionTimeout = 5;/设立超时时间为5秒m_pConnection-Open(Data Source=adotest;,adModeUnknown);State属性指明当前Conn
17、ection对象状态,0表达关闭,1表达已经打开,咱们可以通过读取这个属性来作相应解决,例如:if(m_pConnection-State) m_pConnection-Close();/如果已经打开了连接则关闭它执行SQL命令并获得成果记录集为了获得成果记录集,咱们定义一种指向Recordset对象指针:_RecordsetPtr m_pRecordset;并为其创立Recordset对象实例:m_pRecordset.CreateInstance(ADODB.Recordset);SQL命令执行可以采用各种形式,下面咱们一进行阐述。1) 运用Connection对象Execute办法执行S
18、QL命令,Execute办法原型如下所示:_RecordsetPtr Connection15:Execute ( _bstr_t CommandText,VARIANT * RecordsAffected,long Options )其中CommandText是命令字串,普通是SQL命令。参数RecordsAffected是操作完毕后所影响行数,参数Options表达CommandText中内容类型,Options可以取如下值之一:n adCmdText:表白CommandText是文本命令n adCmdTable:表白CommandText是一种表名n adCmdProc:表白Comman
19、dText是一种存储过程n adCmdUnknown:未知Execute执行完后返回一种指向记录集指针,下面咱们给出详细代码并作阐明。_variant_t RecordsAffected;/执行SQL命令:CREATE TABLE创立表格users,users包括四个字段:整形ID,字符串username,整形old,日期型birthdaym_pConnection-Execute(CREATE TABLE users(ID INTEGER,username TEXT,old INTEGER,birthday DATETIME),&RecordsAffected,adCmdText);/往表格
20、里面添加记录m_pConnection-Execute(INSERT INTO users(ID,username,old,birthday) VALUES (1,Washington,25,1970/1/1),&RecordsAffected,adCmdText);/将所有记录old字段值加一m_pConnection-Execute(UPDATE users SET old = old+1,&RecordsAffected,adCmdText);/执行SQL记录命令得到包括记录条数记录集m_pRecordset = m_pConnection-Execute(SELECT COUNT(*)
21、 FROM users,&RecordsAffected,adCmdText);_variant_t vIndex = (long)0;_variant_t vCount = m_pRecordset-GetCollect(vIndex);/获得第一种字段值放入vCount变量m_pRecordset-Close();/关闭记录集CString message;message.Format(共有%d条记录,vCount.lVal);AfxMessageBox(message);/显示当前记录条数2) 运用Command对象来执行SQL命令_CommandPtr m_pCommand;m_pCo
22、mmand.CreateInstance(ADODB.Command);_variant_t vNULL;vNULL.vt = VT_ERROR;vNULL.scode = DISP_E_PARAMNOTFOUND;/定义为无参数m_pCommand-ActiveConnection = m_pConnection;/非常核心一句,将建立连接赋值给它m_pCommand-CommandText = SELECT * FROM users;/命令字串m_pRecordset = m_pCommand-Execute(&vNULL,&vNULL,adCmdText);/执行命令,获得记录集在这段代
23、码中咱们只是用Command对象来执行了SELECT查询语句,Command对象在进行存储过程调用中能真正体现它作用。下次咱们将详细简介。3) 直接用Recordset对象进行查询获得记录集。 例如:m_pRecordset-Open(SELECT * FROM users,_variant_t(IDispatch *)m_pConnection,true),adOpenStatic,adLockOptimistic,adCmdText);Open办法原型是这样:HRESULT Recordset15:Open ( const _variant_t & Source,const _varian
24、t_t & ActiveConnection,enum CursorTypeEnum CursorType,enum LockTypeEnum LockType,long Options ) 其中:u Source是数据查询字符串u ActiveConnection是已经建立好连接(咱们需要用Connection对象指针来构造一种_variant_t对象) u CursorType光标类型,它可以是如下值之一,请看这个枚举构造:enum CursorTypeEnumadOpenUnspecified = -1,/不作特别指定adOpenForwardOnly = 0,/前滚静态光标。这种光标只
25、能向前浏览记录集,例如用MoveNext向前滚动,这种方式可以提高浏览速度。但诸如BookMark,RecordCount,AbsolutePosition,AbsolutePage都不能使用adOpenKeyset = 1,/采用这种光标记录集看不到其他顾客新增、删除操作,但对于更新原有记录操作对你是可见。adOpenDynamic = 2,/动态光标。所有数据库操作都会及时在各顾客记录集上反映出来。adOpenStatic = 3/静态光标。它为你记录集产生一种静态备份,但其他顾客新增、删除、更新操作对你记录集来说是不可见。;u LockType锁定类型,它可以是如下值之一,请看如下枚举构
26、造:enum LockTypeEnumadLockUnspecified = -1,/未指定adLockReadOnly = 1,/只读记录集adLockPessimistic = 2,/悲观锁定方式。数据在更新时锁定其他所有动作,这是最安全锁定机制adLockOptimistc = 3,/乐观锁定方式。只有在你调用Update办法时才锁定记录。在此之前依然可以做数据更新、插入、删除等动作adLockBatchOptimistic = 4,/乐观分批更新。编辑时记录不会锁定,更改、插入及删除是在批解决模式下完毕。;Options请参照本文中对Connection对象Execute办法简介记录集
27、遍历、更新依照咱们刚才通过执行SQL命令建立好users表,它包括四个字段:ID,username,old,birthday如下代码实现:打开记录集,遍历所有记录,删除第一条记录,添加三条记录,移动光标到第二条记录,更改其年龄,保存到数据库。_variant_t vUsername,vBirthday,vID,vOld;_RecordsetPtr m_pRecordset;m_pRecordset.CreateInstance(ADODB.Recordset);m_pRecordset-Open(SELECT * FROM users,_variant_t(IDispatch*)m_pConn
28、ection,true),adOpenStatic,adLockOptimistic,adCmdText);while(!m_pRecordset-adoEOF)/这里为什么是adoEOF而不是EOF呢?还记得rename(EOF,adoEOF)这一句吗? vID = m_pRecordset-GetCollect(_variant_t(long)0) );/获得第1列值,从0开始计数,你也可以直接给出列名称,如下一行vUsername = m_pRecordset-GetCollect(username);/获得username字段值vOld = m_pRecordset-GetCollec
29、t(old);vBirthday = m_pRecordset-GetCollect(birthday);/在DEBUG方式下OUTPUT窗口输出记录集中记录if(vID.vt != VT_NULL & vUsername.vt != VT_NULL & vOld.vt != VT_NULL & vBirthday.vt != VT_NULL)TRACE(id:%d,姓名:%s,年龄:%d,生日:%sr,vID.lVal,(LPCTSTR)(_bstr_t)vUsername,vOld.lVal,(LPCTSTR)(_bstr_t)vBirthday) ;m_pRecordset-MoveNe
30、xt();/移到下一条记录 m_pRecordset-MoveFirst();/移到首条记录 m_pRecordset-Delete(adAffectCurrent);/删除当前记录 /添加三条新记录并赋值for(int i=0;iAddNew();/添加新记录 m_pRecordset-PutCollect(ID,_variant_t(long)(i+10);m_pRecordset-PutCollect(username,_variant_t(叶利钦);m_pRecordset-PutCollect(old,_variant_t(long)71);m_pRecordset-PutColle
31、ct(birthday,_variant_t(1930-3-15); m_pRecordset-Move(1,_variant_t(long)adBookmarkFirst);/从第一条记录往下移动一条记录,即移动到第二条记录处 m_pRecordset-PutCollect(_variant_t(old),_variant_t(long)45);/修改其年龄m_pRecordset-Update();/保存到库中关闭记录集与连接记录集或连接都可以用Close办法来关闭 m_pRecordset-Close();/关闭记录集m_pConnection-Close();/关闭连接至此,咱们已经熟
32、悉了ADO操作数据库大体流程,也许您已经胸有成竹,也许您尚有点胡涂,不要紧!建议你尝试写几种例子,这样会更好地熟悉ADO,最后我给人们写了一种小例子,例子中读出所有记录放到列表控件中、并可以添加、删除、修改记录。例1:通过ADO控件访问数据严格按课中所说,应可以建立一种简朴基于ADO控件访问数据库程序。请人们自行做一下。例2:通过ADO对象实现数据访问演示一种学生信息录入和管理程序1) 建立一种Access 数据库student.mdb,建立一种表,名称Student,字段分别为:SNo数字Name-字串Birthday日期EnglishGrad四级成绩COmputerGradeVC成绩2)
33、在一种暂时VC程序中通过ADO连接控件得到Access 数据库student.mdb连接字串3) 建立一种正式基于对话框MFC程序4) 建立下面对话框界面,其中每个控件属性设立如下。(应用程序对话框界面)(对话框上各控件属性设立)控件类型属性值相应成员变量分组框控件IDIDC_STATICCaption学生信息编辑框控件IDIDC_EDIT1m_NoIDIDC_EDIT2m_NameIDIDC_EDIT3m_AddressIDIDC_EDIT4m_DateIDIDC_EDIT5m_Score按钮IDID_OKCaption拟定IDIDC_BUTTON1CaptionNEXTIDIDC_BUTT
34、ON2CaptionPREVIDIDC_BUTTON3CaptionLASTIDIDC_BUTTON4CaptionFIRSTIDIDC_BUTTON2CaptionAddIDIDC_BUTTON2CaptionDELETEIDIDC_BUTTON2CaptionSAVE5) 对话框类中成员变量定义:CStringm_No;CStringm_Name;CStringm_Address;CStringm_Date;CStringm_Score;_ConnectionPtr m_pCon;_RecordsetPtr m_pRs;_variant_t vFieldValue;6) 对话框类中初始化中
35、数据连接初始化功能m_pCon.CreateInstance(_uuidof(Connection);m_pCon-Open(Provider=Microsoft.Jet.OLEDB.4.0;Data Source=db1.mdb;Persist Security Info=False ,-1);/Provider=Microsoft.Jet.OLEDB.4.0;Data Source=E:MYVCVCNo9-ADOdb1.mdb/Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:课程VCNo9-ADOdb1.mdb;Persist Security
36、 Info=Falsem_pRs.CreateInstance(_uuidof(Recordset);m_pRs-Open(select * from Test,m_pCon.GetInterfacePtr(),adOpenDynamic,adLockOptimistic,adCmdText);m_pRs-MoveFirst();DispFileds();7) DispFileds()函数用于更新对话框显示。定义如下:void CADObjectDlg:DispFileds()vFieldValue=m_pRs-GetCollect(NO);strFiledValue = (char*)_bs
37、tr_t(vFieldValue);m_No = strFiledValue;vFieldValue.Clear();vFieldValue=m_pRs-GetCollect(NAME);if (vFieldValue.vt !=VT_NULL)strFiledValue = (char*)_bstr_t(vFieldValue);elsestrFiledValue =;m_Name = strFiledValue;vFieldValue.Clear();vFieldValue=m_pRs-GetCollect(ADDRESS);if (vFieldValue.vt!=VT_NULL)strF
38、iledValue = (char*)_bstr_t(vFieldValue);elsestrFiledValue =;m_Address = strFiledValue;vFieldValue.Clear();vFieldValue=m_pRs-GetCollect(Date);if (vFieldValue.vt!=VT_NULL)strFiledValue = (char*)_bstr_t(vFieldValue);elsestrFiledValue =;m_Date = strFiledValue;vFieldValue.Clear();vFieldValue=m_pRs-GetCol
39、lect(Score);if (vFieldValue.vt!=VT_NULL)strFiledValue = (char*)_bstr_t(vFieldValue);elsestrFiledValue =;m_Score = strFiledValue;vFieldValue.Clear();UpdateData(false);8) 记录移动按钮m_pRs-MoveNext();if (m_pRs-adoEOF=VARIANT_FALSE)DispFileds();elsem_pRs-MovePrevious();AfxMessageBox(have been eof record!);9)
40、 记录增长按钮m_pRs-MoveLast();m_pRs-AddNew();DispFileds();10) 记录删除按钮HRESULT hr = m_pRs-Delete(adAffectCurrent);hr = m_pRs-Update();OnFirst() ;11) 记录保存按钮setFields();该函数定义:void CADObjectDlg:setFields()UpdateData(true);HRESULT hr = m_pRs-put_Collect(CComVariant(0),CComVariant(m_No);m_pRs-put_Collect(CComVari
41、ant(1),CComVariant(m_Name);m_pRs-put_Collect(CComVariant(2),CComVariant(m_Address);m_pRs-put_Collect(CComVariant(3),CComVariant(m_Date);m_pRs-put_Collect(CComVariant(4),CComVariant(m_Score);hr = m_pRs-Update();if (hr!=0)内容总结本章重要解说了ADO编程基本原理和实际操作环节。理解初期数据库访问技术ODBC和DAO,再跟ADO数据库连接技术进行比较。简介使用ADO连接数据库编程技
42、术基本环节。重要数据对象集或者说智能指针重要成员和用法,并在Access小型数据库中建立自己数据库并使用ADO数据库访问技术访问该数据库并进行有关增、删、改操作。独立实践n 实践1解释名词:ADO,连接对象,记录集对象,ADO控件,Accessn 实践2阐明用ADO对象连接数据典型环节n 实践3使用ADO控件和ADO对象建立一种数据应用程序:它能实现简朴学生成绩管理功能,该程序有三个对话框,分别实现学生信息,课程信息和学生考试信息录入和显示功能。n 实践4实现一种简朴SQLPlus软件,界面设计:一种ListCtrl控件,用于显示查询记录成果;一种编辑框控件用于输入SQL语句;一种查询按钮,用于执行该SQL语句。注意:ListCtrl控件表头项是依照查询成果动态变化。如图:(显示所有记录字段信息图例)(显示指定记录字段信息图例)