
一、ADO简介 ADO(ActiveX Data Object)是Microsoft数据库应用程式研发的新接口,是建立在OLE DB之上的高层数据库访问技术,请不必为此担心,即使您对OLE DB,COM不了解也能轻松对付ADO,因为他很简单易用,甚至比您以往所接触的ODBC API、DAO、RDO都要容易使用,并不失灵活性。本文将周详地介绍在VC下怎样使用ADO来进行数据库应用程式研发,并给出示例代码。 本文示例代码
二、基本流程 万事开头难,任何一种新技术对于初学者来说最重要的还是“入门”,掌控其要点。让我们来看看ADO数据库研发的基本流程吧! (1)初始化COM库,引入ADO库定义文档 (2)用Connection对象连接数据库 (3)利用建立好的连接,通过Connection、Command对象执行SQL命令,或利用Recordset对象取得结果记录集进行查询、处理。 (4)使用完毕后关闭连接释放对象。
准备工作: 为了大家都能测试本文提供的例子,我们采用Access数据库,您也能够直接在我们提供的示例代码中找到这个test.mdb。 下面我们将周详介绍上述步骤并给出相关代码。 【1】COM库的初始化 我们能够使用AfxOleInit()来初始化COM库,这项工作通常在CWinApp::InitInstance()的重载函数中完成,请看如下代码:
BOOL CADOTest1App::InitInstance()
} catch(_com_error e)///捕获异常
在这段代码中我们是通过Connection对象的Open方法来进行连接数据库的,下面是该方法的原型 HRESULT Connection15::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:允许其他程式或对象以任何权限建立连接
我们给出一些常用的连接方式供大家参考: (1)通过JET数据库引擎对ACCESS2000数据库的连接
m_pConnection->Open("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:test.mdb","","",adModeUnknown);
(2)通过DSN数据源对任何支持ODBC的数据库进行连接: m_pConnection->Open("Data Source=adotest;UID=sa;PWD=;","","",adModeUnknown);
(3)不通过DSN对SQL SERVER数据库进行连接: m_pConnection->Open("driver=;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(); ///假如已打开了连接则关闭他
【4】执行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("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);///执行命令,取得记录集
在这段代码中我们只是用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 _variant_t & ActiveConnection, enum CursorTypeEnum CursorType, enum LockTypeEnum LockType, long Options ) 其中: ①Source是数据查询字符串 ②ActiveConnection是已建立好的连接(我们需要用Connection对象指针来构造一个_variant_t对象) ③CursorType光标类型,他能够是以下值之一,请看这个枚举结构: enum CursorTypeEnum ; ④LockType锁定类型,他能够是以下值之一,请看如下枚举结构: enum LockTypeEnum ; ⑤Options请参考本文中对Connection对象的Execute方法的介绍
【5】记录集的遍历、更新 根据我们刚才通过执行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),adOpenStatic,adLockOptimistic,adCmdText); while(!m_pRecordset->adoEOF)///这里为什么是adoEOF而不是EOF呢?还记得rename("EOF","adoEOF")这一句吗?
m_pRecordset->MoveFirst();///移到首条记录 m_pRecordset->Delete(adAffectCurrent);///删除当前记录 ///添加三条新记录并赋值 for(int i=0;i<3;i++)
m_pRecordset->Move(1,_variant_t((long)adBookmarkFirst));///从第一条记录往下移动一条记录,即移动到第二条记录处 m_pRecordset->PutCollect(_variant_t("old"),_variant_t((long)45));///修改其年龄 m_pRecordset->Update();///保存到库中
【6】关闭记录集和连接 记录集或连接都能够用Close方法来关闭 m_pRecordset->Close();///关闭记录集 m_pConnection->Close();///关闭连接
至此,我想您已熟悉了ADO操作数据库的大致流程,也许您已胸有成竹,也许您更有点胡涂,不要紧!建议您尝试写几个例子,这样会更好地熟悉ADO,最后我给大家写了一个小例子,例子中读出任何记录放到列表控件中、并能够添加、删除、修改记录。 点这里下载示例代码
后记:限于篇幅ADO中的许多内容还没有介绍,下次我们将周详介绍Recordset对象的属性、方法并解决几个关键的技术:绑定方式处理记录集数据、存储过程的调用、事务处理、图象在数据库中的保存和读取、和表格控件的配合使用等
//-------------------------------------------------------------------------------------- 又一个说明: 在vc中怎么使用ADO访问数据库?
1、#import "msado15.dll" no_namespace rename("EOF","ADOEOF") 引入"msado15.dll"动态库。
2、定义一个变量 _ConnectionPtr m_AdoCon;代表一个代表和数据源进行的唯一会话
3、打开数据库 _bstr_t connString; //连接字符串
try
catch (_com_error& comerr)
}
4、使用 CString strIp, SQL_STR, strTemp, strResult;
UINT port;
_RecordsetPtr AdoRst; //RecordSet的实例 _StreamPtr AdoStream; //Ado数据流
SQL_STR = m_strText; //SQL语句
if (m_AdoCon->State == adStateClosed) //判断连接是否已关闭
try
} catch (_com_error& comerr)
}
5.取得表中的字段 GetCollect() int nItem; _variant_t vUsername,vBirthday,vID,vOld; try
}
6.添加数据 PutCollect() if(!m_pRecordset->adoEOF && m_nCurrentSel >= 0 && m_bAutoSave)
//-------------------------------------------------------------------------------------- 在ado中获取access中表的信息
void OpenSchemaX(TCHAR *TableName) { HRESULT hr = S_OK;
IADORecordBinding *picRs = NULL;
_RecordsetPtr pRstSchema("ADODB.Recordset"); _ConnectionPtr pConnection("ADODB.Connection" );
pConnection->ConnectionString = TableName; pConnection->Provider = "Microsoft.Jet.OLEDB.4.0";
try { pConnection->Open(pConnection->ConnectionString, "", "", adModeUnknown); pRstSchema->QueryInterface( __uuidof(IADORecordBinding), (LPVOID*)&picRs);
pRstSchema = pConnection->OpenSchema(adSchemaTables);//枚举表的名称处理
while(!(pRstSchema->EndOfFile))
pRstSchema->MoveNext(); } // Clean up objects before exit.
pRstSchema->Close(); pConnection->Close(); }
catch (_com_error &e) }
|