锐英源软件
第一信赖

精通

英语

开源

擅长

开发

培训

胸怀四海 

第一信赖

当前位置:锐英源 / 英语翻译 / VC++下ADO数据库访问技术
服务方向
人工智能数据处理
人工智能培训
kaldi数据准备
小语种语音识别
语音识别标注
语音识别系统
语音识别转文字
kaldi开发技术服务
软件开发
运动控制卡上位机
机械加工软件
软件开发培训
Java 安卓移动开发
VC++
C#软件
汇编和破解
驱动开发
联系方式
固话:0371-63888850
手机:138-0381-0136
Q Q:396806883
微信:ryysoft

锐英源精品开源心得,转载请注明:“锐英源www.wisestudy.cn,孙老师作品,电话13803810136。”需要全文内容也请联系孙老师。英文原文

简介

ADO使用OLEDB提供者来操纵和存储数据,且因为它提供了双向接口,你能在脚本语言里使用它,比如VBScript和JavaScript,也可以在C++语言里使用。它也有很多其它优点,比如高速,低内存消耗,最重要的是,它易于使用。
在这个简短的文章里,我将会描述出怎样开始使用ADO,比如,怎样打开记录集recordset,查询数据库或者执行存储过程。
先说一下前提条件。本文所设定环境如下:例子数据库ADOTestDB.MDB,VC++ 6 (SP3)和ADO 2.1。在数据库里,只有两个简单的表,名称为Student和Dept,它们的字段和类型各不一样,也有一些例子数据。使用import指令来获取ADO的智能指针特性。
在你的stdafx.h文件里输入如下代码:

#import "msado15.dll" \
no_namespace \
rename( "EOF", "adoEOF" )

把EOF重命名为adoEOF,来防止你的应用程序受某些讨厌的冲突干扰。
上面代码添加过后,你需要初始化COM来使用ADO。为了实现初始化,调用CoInitialize(NULL)函数,调用放到你代码开始的位置,在使用过ADO之后,记得调用CoUninitialize()。

实现一上对数据库服务器的连接

存取数据库的第一步是连接到数据源。为了连接到数据源,你要使用ADO的Connection对象。ADO建立连接的主要办法是通过Connection的Open成员函数。浏览一下下面的代码(为了代码简洁,错误处理忽略了):

_ConnectionPtr m_pConn;
m_pConn.CreateInstance (__uuidof(Connection));
m_pConn->Open ( 
_bstr_t ( "Provider=Microsoft.Jet.OLEDB.4.0;
Data Source = ADOTestDB.MDB" ),
_bstr_t ( "" ),
_bstr_t ( "" ),
adModeUnknown );

T这段代码是通过Microsoft.Jet.OLEDB.4提供者建立到ADOTestDB.MDB数据库连接的代码片段。首先,你必须定义一个_ConnectionPtr(ADO Connection)类型的对象,接着你初始化它,最后调用Open函数。Open函数的第一个参数是连接字符串,这个参数指明了你尝试连接的数据源和OLEDB提供者。随后两个参数指明UserName和Password来登录进入到数据库。我们的例子数据库不需要任何用户,所以你能用空字符串,最后一个参数是选项Options,它决定了打开是异步或者同步的。如果你不知道这个特性,你能简单地用adModeUnknown。
使用ODBC驱动来连接数据源也是一个不错的想法,如下的代码显示了怎样使用它:

m_pConn->Open (_bstr_t ("DSN=pubs;uid=sa;pwd=;"),
_bstr_t (""),
_bstr_t (""),
adCmdUnknown );

构造SQL语句

在ADO内,有不同的办法来构造SQL语句。最常用的办法是使用Command对象。Command是一个指令,数据提供者能够解释这个指令来修改管理和操纵数据源,这些指令以SQL格式编写。现在,我们要query查询Student表里的所有学生数据。代码如下:

_CommandPtr pCommand;
pCommand.CreateInstance (__uuidof (Command));
pCommand->ActiveConnection = m_pConn; // Formerly opened connection
// pointer
pCommand->CommandText = "Select * From Student";

如同你看到的,首先,我们声明一个Command对象,接着初始化它。随后,我们设置ActiveConnection属性为先前打开的连接对象,m_pConn。CommandText属性表示查询、SQL语句或者存储过程名称,它会被提供者处理,对于我们的使用来说,它就是一个简单的查询,"Select * From Student"。
当我们的命令文本查询时,通过处理,它会返回一个行的集合,我们应该把这个集合存储到某些地方。 了实现此目的,我们定义了一个Recordset对象,它会存储返回的记录行,且让你能够操纵这些记录行。
现在,我们将要执行这个命令,但是我要提醒的是。有两个办法来执行ADO的命令,第一个是通过Command的Execute成员函数,另外一个是Recordset的Open成员函数。这里我们通过Recordset的Open来实现:

_RecordsetPtr pRecordset;
pRecordset.CreateInstance (__uuidof (Recordset));
pRecordset->CursorLocation = adUseClient;
pRecordset->Open ( (IDispatch *) pCommand, vtMissing, adOpenStatic,
adLockBatchOptimistic, adCmdUnknown);

在这段摘抄的代码里,我们先定义一个Recordset类型的对象,接着初始化它。在ADO里,Recordset对象有几十个属性,各有各的目的,我们使用的属性是CursorLocation,它让你指定在客户端和服务器端之间的游标的位置。属性设置过后,你能调用Open函数来处理对应数据源的命令。Open函数的第一个参数指定了一个变体变量(其值为Command对象、SQL语句、表名、存储过程或者一个被理解为源Source的URL)。第二个参数是一个活动的连接对象,是个可选参数。由于我们在Command对象里指定连接,这里就不需要连接参数了,只是简单地忽略参数(用值为DISP_E_PARAMNOTFOUND 类型为VT_ERROR 的变体变量_variant_t 来表示,也可用变体变量的常量vtMissing 来表示,vtMissing是由 #import指令引入的)。第三个和第四个参数是游标类型和锁定类型。锁定类型为adLockBatchOptimistic,这是因为我们要用到批处理,且因为这个处理需要游标服务cursor services ,我们在前面指定游标位置。如果有不同于Command对象的别的情况,最后的参数指示提供者应该怎样评价源Source参数,但是我们的源Source恰好是一个command对象,所以简单地设置最后参数是adCmdUnknown。现在,在调用了Open函数后,你就有了含有所有学生信息的Recordset对象。

操纵数据

这里,我们将修改一些数据。在Student表里有一个字段SocialSecNo,这个字段显示每个学生社会安全号码,它必须从类似’45’开头的修改为以’77’开头。所以我们必须修改所有的以’45’开头的记录到’77’开头的形式。为了实现这个任务,我们为以’45’开头的SocialSecNo来进行过滤,而且,我们将设置StudentNo字段做为记录集的索引,以使排序和过滤性能提高。
此时你可能想,以上面所说方法来实现如下要求可能效率低,且依赖于情形有可能是正确的,但我的最重要的目的是,介绍ADO的不同能力,所以不要考虑效率的事情,高高兴兴用ADO的特性。
操纵数据的代码如下:

pRecordset->Fields->GetItem ("StudentNo")->Properties->
GetItem ("Optimize")->Value = VARIANT_TRUE;
pRecordset->Sort = "Name";
pRecordset->Filter = "SocialSecNo LIKE '45*'";
while (!pRecordset->GetadoEOF())
CString str = (char *) (_bstr_t) pRecordset->Fields->
GetItem("SocialSecNo")->Value;
str = "77" + str.Right(str.GetLength() - 2);
pRecordset->Fields->GetItem("SocialSecNo")->Value = 
(_bstr_t) str;
pRecordset->MoveNext();
}
pRecordset->Filter = (long) adFilterNone;

在上面代码里,我们设置StudentNo成员的Optimize属性为真来使它为记录集的索引,接着,我们以Name字段来排序,以’45’开头的SocialSecNo字段为过滤。在while循环里,我们只简单地修改SocialSecNo值来新值,并向下移动记录集的游标指针。当你修改了SocialSecNo字段为新值后,它的新值不再匹配过滤条件,所以它对记录集不可见。为了记录集的重新表现,我们应该在最后删除过滤器。

更新数据

在ADO里有两种办法来更新数据。第一个方法是立即更新,它意味着一旦你调用Update函数,你对记录集直接实现了修改,且由此影响了数据源。但是第二个办法被认为是Batch模式更新。如果你以adLockBatchOptimistic锁定类型打开记录集,ADO让你以Batch模式来更新数据。在Batch模式下,对记录的移动或者调用Update函数在一个拷贝缓冲里实现更新,且只在调用了BatchUpdate函数后,修改才被通知到数据源里。
在我们的例子里,我们使用Batch模式,所以你能用以下代码来通知修改:

pRecordset->BatchUpdate (adAffectAll );

现在,你学会了怎样打开和查询数据,随后是操纵和更新数据。但是在ADO里还有更多的内容你必须来学习,这些内容中,最重要的是调用存储过程和参数化命令。

带输入参数执行存储过程

调用存储过程就象上面所说打开记录集一样容易。有一些细小的注意来创建输入参数和赋值,随后的代码会讨论这些。在ADO里传递参数有两个办法,第一个是通过Parameter对象,第二个是通过Refresh方法,但是我偏向于第一上方法,因为在性能上有优势。
这里,我介绍第一个办法。如下的代码行显示你怎样用Parameter对象设置输入参数和执行数据库里的Query1存储过程

_CommandPtr pCommand;
_ParameterPtr pParam1, pParam2;
CString str("Ma%");
pCommand.CreateInstance(__uuidof(Command));
pCommand->ActiveConnection = m_pConn; //Its the connection pointer
//we opened formerly
pCommand->CommandText = "Query1";
pCommand->CommandType = adCmdStoredProc;
pParam1 = pCommand->CreateParameter ( _bstr_t ("DeptID"), adTinyInt,
adParamInput, sizeof (BYTE), 
_variant_t ( long (11)));
pCommand->Parameters->Append ( pParam1);
pParam2 = pCommand->CreateParameter ( _bstr_t ("Name"), adVarChar,
adParamInput, str.GetLength (),
(_bstr_t) str);
pCommand->Parameters->Append ( pParam2);
_RecordsetPtr pRecordset;
pRecordset.CreateInstance(__uuidof(Recordset));
pRecordset = pCommand->Execute(NULL, NULL, adCmdStoredProc);

代码开始,创建一个Command对象,接着设置ActiveConnection属性到一个已经打开的连接上,随后,在CommandText里指明你的存储过程的名称,对CommandType属性设置为adCmdStoredProc值。因为存储过程有两个输入参数,所以声明两个Parameter对象,接着通过调用CreateParameter方法来创建他们。CreateParameter的第一个参数指向一个可选的参数名称,第二个指明参数的类型,第三个决定参数是输入还是输出。笼四上参数代表变量的长度,第5个指明参数的值。
在指明了参数后,创建的参数分别被赋值给pParam1和Pparam2。创建的参数接着应该被添加(Appended)到Parameters集,为了达到此目的,我们调用了Append方法。现在,你的命令Command准备好执行了。
对于例子数据库里的Query1存储过程,你看一下就会理解,里面是一个简单的查询语句,它会返回一个rowset(记录集),所以在执行了command对象后,它可能返回一个存储在Recordset对象里的记录集。

错误处理机制

对于上面引用的例子,为了代码的简洁性,我没有考虑错误处理。这里,我会讲述一个简单的错误处理,你可以代码里使用ADO的关键的任何地方来使用这个错误处理。通常情况下,因为ADO使用了COM,所以它抛出的是异常类型是_com_error,使用try-catch块来处理_com_error就可以实现异常处理:

try
{
HRESULT hr = m_pConn.CreateInstance(__uuidof(Connection));
if (FAILED( hr ))
AfxMessageBox(
"Can't create an intance of ADO.Connection" );
if (FAILED( m_pConn->Open(
_bstr_t(
"Provider=Microsoft.Jet.OLEDB.4.0;Data Source = 
ADOTestDB.MDB"), _bstr_t( "" ), _bstr_t( "" ),adModeUnknown )))
AfxMessageBox( "Can't open datasource" );
...
...
...
m_pConn->Close();
}
catch( _com_error &e )
{
_bstr_t bstrSource(e.Source());
_bstr_t bstrDescription(e.Description());
TRACE( "Exception thrown for classes generated by #import" );
TRACE( "\tCode = %08lx\n", e.Error());
TRACE( "\tCode meaning = %s\n", e.ErrorMessage());
TRACE( "\tSource = %s\n", (LPCTSTR) bstrSource);
TRACE( "\tDescription = %s\n", (LPCTSTR) bstrDescription);
}
catch (...)
{
TRACE ( "*** Unhandled Exception ***" );
}

在上面代码里,Open函数调用不能发现在目录里的mdf文件,所以它产生一个决定了错误类型和编码的异常,另外还有一个关于错误的简洁描述。

友情链接
版权所有 Copyright(c)2004-2021 锐英源软件
公司注册号:410105000449586 豫ICP备08007559号 最佳分辨率 1024*768
地址:郑州大学北校区院(文化路97号院)内