第十二章ADO编程关键技术
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
第十二:ADO编程技术
学习目的
⏹ADO编程技术简介
⏹ADO对象构造
⏹使用ADO控件访问数据
⏹使用ADO对象访问数据
ADO编程技术简介
三种数据库数据库访问技术简介:
⏹ODBC(Open Database Connectivity,开放式数据库连接),是一
种用来在有关或不有关数据库管理系统(DBMS)中存取数据原则应用程序接口(API)。
⏹DAO(Data Access Object )即数据访问对象集,是Microsoft提
供基于一种数据库对象集合访问技术。
和ODBC同样,她们都是Windows API一某些,可以独立于(DBMS)进行数据库访问。
DAO跟ODBC区别是:访问机制不同!ODBC工作依赖于数据库制造商提供驱动程序。
使用ODBC API时候,WindowsODBC管理程序,把对数据库访问祈求传递给对的驱动程序,驱动程序再使用SQL语句批示DBMS 完毕数据库访问工作。
ADO则绕开中心环节,直接使用数据库引擎(Microsoft Jet Database Engine)提供数据库访问对象集进行工作。
速度比ODBC快。
⏹ADO(ActiveX Data Object)是Microsoft数据库应用程序开发新
接口,是建立在OLE DB之上高层数据库访问技术,提供了简朴易用访问各种数据资源(涉及关系型和非关系型)。
是相对比较新数据库访问技术。
ADO是Microsoft数据库应用程序开发新接口,是建立在OLE DB之上高层数据库访问技术,请不必为此紧张,虽然你对OLE DB,COM不理解也能轻松对付ADO,由于它非常简朴易用,甚至比你以往所接触ODBC API、DAO、RDO都要容易使用,并不失灵活性。
本文将详细地简介在VC下如何使用ADO 来进行数据库应用程序开发。
ADO对象构造
ADO是一种面向对象组件库,用ADO访问数据库,其实就是运用ADO对象来操作数据如数据,因此咱们一方面要撑握ADO对象
⏹连接对象(connection):
连接用于与数据库建立连接,执行查询及进行事务解决。
在连接时必要要指定使用何种数据库OLEDB供应者
⏹命令对象(Command):
可以执行数据库操作命令(如查询,修改,增长和删除)。
用命令对象执行一种查询字串,可以返回一种记录集合。
⏹记录集对象(Recordset):
用于表达查询返回成果集,它可以在成果集中增长,删除,修改和移动刻录。
当建立一种记录集时,一种游标就自动建立了,查询所产生记录就放在本地游标中,游标有四种类型:仅能向前移动游标,静态游标,键集游标和动态游标。
记录集对象是对数据库进行查询和修改重要对象。
⏹字段对象(Fields字段集合对象,Field字段对象):
字段对象用于表达数据库或记录集中信息,涉及列值等信息。
一种记录集或一种数据库中表涉及了多行记录,若将其当做二维网格,字段将是网格中列,每个字段分别有名称,数据类型和值等属性,字段中涉及了来自数据库源中真实数据。
要修改其中数据可在集录集修改Filed字段对象,也可以通过在刻录集中访问Fields字段集合对象,再定位要修改Filed字段对象。
对记录集修改将最后被传送给数据库。
⏹参数对象(Parameter):
是和命令对象联用一种对象。
当命令对象执行查询是一种有参数查询时,就要用参数对象来为命令对象提供参数信息和数据。
使用ADO访问数据库有两种方式:
◆通过ADO控件访问数据库
◆通过ADO对象访问数据库
下面咱们将详细讲述这两种访问数据库办法。
使用ADO控件访问数据库
Access 是Microsoft Office中一种组件,是一种小型桌面数据系统,咱们将以它为例子,解说使用ADO控件访问数据库办法。
⏹在Access 建立空数据库(参见Access 操作信息)
⏹在空数据库中建立一种名称为test一种表(参见Access 操作信息)⏹建立一种VC基于对话框程序框架(也可以是其他向导建立手框架)
⏹在对话框界面编辑器中增长一种ADO控件。
ADO控件有各种类型:
◆ADO Data连接控件,用于以便建立数据连接
◆ADO Grid控件,用于表达一种记录成果集
在对话框编辑器,右键菜单中选取Insert ActiveX Control,在浮现对话框中选取Microsoft ADO Data Control,Version 6.0,点OK即可以将连接控件加入到对话框中,同样办法选取Microsoft ADO Grid Control,Version 6.0加入到对话框中。
⏹设立对话框中连接控件属性
上述两个控件属性设立和VC中其他控件设立是同样。
连接控件属性设立:在属性对话框中选取Control页面,选取Use Connection String选项,点Build按钮,在浮现对话框中选取Microsoft Jet 4.0 OLEDB Provider提供者。
点下一步选取刚建立Access 数据文献名称。
点测试连接应能连接数据库通过。
再一次打开连接控件属性设立,选取RecordeSource页面,在Command Type中选取2-adCmdTable,在Table Or StoredProcedure Name 中选取刚建立test表。
到此完毕一连接控件设立。
⏹设立对话框中Grid控件属性
同样办法打开Grid控件属性对话框。
选取Control页面,选中Allow AddNew和Allow Delete复选框,再选取All页面,设立DataSource 参数为连接控件ID
⏹运营该程序
将可以在对话框中连接数据库,并取出表中数据显示在Grid控件中。
使用ADO对象访问数据库
ADO数据库开发基本流程
⏹初始化COM库,引入ADO库定义文献
⏹用Connection对象连接数据库
⏹运用建立好连接,通过Connection、Command对象执行SQL命令,或
运用Recordset对象获得成果记录集进行查询、解决。
⏹使用完毕后关闭连接释放对象。
咱们采用Access数据库,您也可以直接在咱们提供示例代码中找到这个test.mdb。
下面咱们将详细简介上述环节并给出有关代码。
COM库初始化
咱们可以使用AfxOleInit()来初始化COM库,这项工作普通在CWinApp::InitInstance()重载函数中完毕,请看如下代码:
BOOL CADOTest1App::InitInstance() { AfxOleInit();...... 用#import指令引入ADO类型库
咱们在stdafx.h中加入如下语句:(stdafx.h这个文献哪里可以找到?你可以在FileView中Header Files里找到)
#import "c:program filescommon filessystemadomsado15.dll" no_namespace rename("EOF","adoEOF")
这一语句有何作用呢?其最后作用同咱们熟悉#include类似,编译时候系统会为咱们生成msado15.tlh,ado15.tli两个C++头文献来定义ADO库。
几点阐明:
⏹您环境中msado15.dll不一定在这个目录下,请按实际状况修改
⏹在编译时候肯能会浮现如下警告,对此微软在MSDN中作了阐明,并建议
咱们不要理睬这个警告。
msado15.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.CreateInstance("ADODB.Connection");///创立Connection对象
if(SUCCEEDED(hr))
{
hr = m_pConnection->Open("Provider=Microsoft.Jet.OLEDB.4.0;D ata Source=test.mdb","","",adModeUnknown);
///连接数据库 ///上面一句中连接字串中Provider是针对ACCESS环境,对于ACCESS97,需要改为:Provider=Microsoft.Jet.OLEDB.3.51;
}
}
catch(_com_error e)///捕获异常
{
CString errormessage;
errormessage.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对象对数据更新允许权,Options可以是如下几种常量:
⏹adModeUnknown:缺省。
当前允许权未设立
⏹adModeRead:只读
⏹adModeWrite:只写
⏹adModeReadWrite:可以读写
⏹adModeShareDenyRead:制止其他Connection对象以读权限打开连
接
⏹adModeShareDenyWrite:制止其他Connection对象以写权限打开
连接
⏹adModeShareExclusive:制止其他Connection对象打开连接
⏹adModeShareDenyNone:容许其他程序或对象以任何权限建立连接。
咱们给出某些惯用连接方式供人们参照:
⏹通过JET数据库引擎对ACCESS数据库连接
m_pConnection->Open("Provider=Microsoft.Jet.OLEDB.4.0;D ata Source=C:\test.mdb","","",adModeUnknown);
⏹通过DSN数据源对任何支持ODBC数据库进行连接:
m_pConnection->Open("Data
Source=adotest;UID=sa;PWD=;","","",adModeUnknown);
⏹不通过DSN对SQL SERVER数据库进行连接:
m_pConnection->Open("driver={SQLServer};Server=127.0.0. 1;DATABASE=vckbase;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属性指明当前Connection对象状态,0表达关闭,1表达已经打开,咱们可以通过读取这个属性来作相应解决,例如:
if(m_pConnection->State) m_pConnection->Close();///如果已经打开了连接则关闭它
执行SQL命令并获得成果记录集
为了获得成果记录集,咱们定义一种指向Recordset对象指针:_RecordsetPtr m_pRecordset;并为其创立Recordset对象实例:m_pRecordset.CreateInstance("ADODB.Recordset");SQL命令执行可以采用各种形式,下面咱们一进行阐述。
1)运用Connection对象Execute办法执行SQL命令,Execute办法原
型如下所示:
_RecordsetPtr Connection15::Execute ( _bstr_t CommandText,VARIANT * RecordsAffected,long Options )
其中CommandText是命令字串,普通是SQL命令。
参数RecordsAffected 是操作完毕后所影响行数,参数Options表达CommandText中内容类型,Options可以取如下值之一:
⏹adCmdText:表白CommandText是文本命令
⏹adCmdTable:表白CommandText是一种表名
⏹adCmdProc:表白CommandText是一种存储过程
⏹adCmdUnknown:未知
Execute执行完后返回一种指向记录集指针,下面咱们给出详细代码并作阐明。
_variant_t RecordsAffected;
//执行SQL命令:CREATE TABLE创立表格users,users包括四个字段:整形ID,字符串username,整形old,日期型birthday
m_pConnection->Execute("CREATE TABLE users(ID INTEGER,username TEXT,old INTEGER,birthday DATETIME)",&RecordsAffected,adCmdText);
//往表格里面添加记录
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(*) 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_pCommand.CreateInstance("mand");
_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);
///执行命令,获得记录集
在这段代码中咱们只是用Command对象来执行了SELECT查询语句,Command对象在进行存储过程调用中能真正体现它作用。
下次咱们将详细简介。
3)直接用Recordset对象进行查询获得记录集。
例如:
m_pRecordset->Open("SELECT * FROM users",_variant_t((IDispatch
*)m_pConnection,true),adOpenStatic,adLockOptimistic,adC mdText);
Open办法原型是这样:
HRESULT Recordset15::Open ( const _variant_t & Source,const _variant_t & ActiveConnection,enum CursorTypeEnum CursorType,enum LockTypeEnum LockType,long Options ) 其中:
◆Source是数据查询字符串
◆ActiveConnection是已经建立好连接(咱们需要用Connection
对象指针来构造一种_variant_t对象)
◆CursorType光标类型,它可以是如下值之一,请看这个枚举构造:
enum CursorTypeEnum
{
adOpenUnspecified = -1,
///不作特别指定
adOpenForwardOnly = 0,
//前滚静态光标。
这种光标只能向前浏览记录集,例如用
MoveNext向前滚动,这种方式可以提高浏览速度。
但诸如
BookMark,RecordCount,AbsolutePosition,AbsoluteP
age都不能使用
adOpenKeyset = 1,
//采用这种光标记录集看不到其他顾客新增、删除操作,但对于
更新原有记录操作对你是可见。
adOpenDynamic = 2,
///动态光标。
所有数据库操作都会及时在各顾客记录集上反映
出来。
adOpenStatic = 3
//静态光标。
它为你记录集产生一种静态备份,但其他顾客新增、
删除、更新操作对你记录集来说是不可见。
};
LockType锁定类型,它可以是如下值之一,请看如下枚举构造:
enum LockTypeEnum
{
adLockUnspecified = -1,
//未指定
adLockReadOnly = 1,
//只读记录集
adLockPessimistic = 2,
//悲观锁定方式。
数据在更新时锁定其他所有动作,这是最安全
锁定机制
adLockOptimistc = 3,
//乐观锁定方式。
只有在你调用Update办法时才锁定记录。
在
此之前依然可以做数据更新、插入、删除等动作
adLockBatchOptimistic = 4,
//乐观分批更新。
编辑时记录不会锁定,更改、插入及删除是在
批解决模式下完毕。
};
Options请参照本文中对Connection对象Execute办法简介
记录集遍历、更新
依照咱们刚才通过执行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_pConnection,true),adOpe nStatic,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->GetCollect("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->MoveNext();
//移到下一条记录 }
m_pRecordset->MoveFirst();
//移到首条记录 m_pRecordset->Delete(adAffectCurrent);
//删除当前记录 ///添加三条新记录并赋值
for(int i=0;i<3;i++)
{
m_pRecordset->AddNew();//添加新记录
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->PutCollect("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();///关闭连接
至此,咱们已经熟悉了ADO操作数据库大体流程,也许您已经胸有成竹,也许您尚有点胡涂,不要紧!建议你尝试写几种例子,这样会更好地熟悉ADO,最后我给人们写了一种小例子,例子中读出所有记录放到列表控件中、并可以添加、删除、修改记录。
例1:通过ADO控件访问数据
严格按课中所说,应可以建立一种简朴基于ADO控件访问数据库程序。
请人们自行做一下。
例2:通过ADO对象实现数据访问――演示一种学生信息录入和管理程序
1)建立一种Access 数据库student.mdb,建立一种表,名称Student,
字段分别为:
SNo-数字
Name-字串
Birthday-日期
EnglishGrad-四级成绩
COmputerGrade-VC成绩
2)在一种暂时VC程序中通过ADO连接控件得到Access 数据库
student.mdb连接字串
3)建立一种正式基于对话框MFC程序
4)建立下面对话框界面,其中每个控件属性设立如下。
(应用程序对话框界面)
(对话框上各控件属性设立)
控件类型属性值相应成员变量分组框控件ID IDC_STATIC
Caption 学生信息
编辑框控件ID IDC_EDIT1 m_No
ID IDC_EDIT2 m_Name
ID IDC_EDIT3 m_Address
ID IDC_EDIT4 m_Date
ID IDC_EDIT5 m_Score
按钮ID ID_OK
Caption 拟定
ID IDC_BUTTON1
Caption NEXT
ID IDC_BUTTON2
Caption PREV
ID IDC_BUTTON3
Caption LAST
ID IDC_BUTTON4
Caption FIRST
ID IDC_BUTTON2
5)对话框类中成员变量定义:
CString m_No;
CString m_Name;
CString m_Address;
CString m_Date;
CString m_Score;
_ConnectionPtr m_pCon;
_RecordsetPtr m_pRs;
_variant_t vFieldValue;
6)对话框类中初始化中数据连接初始化功能
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:\\MYVC\\VC\\No9-ADO\\db1.mdb"
//"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\\课程\\VC\\No9-ADO\\db1.mdb;Persist Security Info=False"
m_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*)_bstr_t(vFieldValue);
m_No = strFiledValue;
vFieldValue.Clear();
vFieldValue=m_pRs->GetCollect("NAME");
if (vFieldValue.vt !=VT_NULL)
strFiledValue = (char*)_bstr_t(vFieldValue);
else
strFiledValue ="";
m_Name = strFiledValue;
vFieldValue.Clear();
vFieldValue=m_pRs->GetCollect("ADDRESS");
if (vFieldValue.vt!=VT_NULL)
strFiledValue = (char*)_bstr_t(vFieldValue);
else
strFiledValue ="";
m_Address = strFiledValue;
vFieldValue.Clear();
vFieldValue=m_pRs->GetCollect("Date");
if (vFieldValue.vt!=VT_NULL)
strFiledValue = (char*)_bstr_t(vFieldValue);
else
strFiledValue ="";
m_Date = strFiledValue;
vFieldValue.Clear();
vFieldValue=m_pRs->GetCollect("Score");
if (vFieldValue.vt!=VT_NULL)
strFiledValue = (char*)_bstr_t(vFieldValue);
else
strFiledValue ="";
m_Score = strFiledValue;
vFieldValue.Clear();
UpdateData(false);
}
8)记录移动按钮
m_pRs->MoveNext();
if (m_pRs->adoEOF==VARIANT_FALSE)
DispFileds();
else
{
m_pRs->MovePrevious();
AfxMessageBox("have been eof record!");
}
9)记录增长按钮
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(CComVariant(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_Scor
e);hr = m_pRs->Update();
if (hr!=0)
{
}
}
本章重要解说了ADO编程基本原理和实际操作环节。
理解初期数据库访问技术ODBC和DAO,再跟ADO数据库连接技术进行比较。
简介使用ADO连接数据库编程技术基本环节。
重要数据对象集或者说智能指针重要成员和用法,并在Access小型数据库中建立自己数据库并使用ADO数据库访问技术访问该数据库并进行有关增、删、改操作。
⏹实践1
解释名词:ADO,连接对象,记录集对象,ADO控件,Access
⏹实践2
阐明用ADO对象连接数据典型环节
⏹实践3
使用ADO控件和ADO对象建立一种数据应用程序:它能实现简朴学生成绩管理功能,该程序有三个对话框,分别实现学生信息,课程信息和学生考试信息录入和显示功能。
⏹实践4
实现一种简朴SQLPlus软件,界面设计:一种ListCtrl控件,用于显示查询记录成果;一种编辑框控件用于输入SQL语句;一种查询按钮,用于执行该SQL语句。
注意:ListCtrl控件表头项是依照查询成果动态变化。
如图:
(显示所有记录字段信息图例)
(显示指定记录字段信息图例)。