ADO主要对象介绍:
ADO对象包括:连接对象(Connection Object)、命令对象(Command Object)、记录集对象(RecordSet Object)、字段对象(Field Object)、记录对象(Record Object)、错误对象(Error Object)、参数对象(Parameter Object)、属性对象(Property Object) 和 流对象(Stream Object)。
其中最重要的3个对象是:连接对象、命令对象 和 记录集对象。
1)连接对象(Connection Object):代表一个和数据源的连接,以后的数据库操作都是建立在这个连接上的。
Connection 对象主要是用来和数据库进行连接,提供了对数据库的操作,但是它不返回数据库操作后的记录集。
2)命令对象(Command Object):用来处理数据库的一些操作,在某方面具有和Connection对象相同的功能。
例如,都可以执行标准的SQL语句 以及 存储过程,不过Command 对象可以返回带有记录集的结果集。
3)记录集对象(RecordSet Object):代表了一个记录集,用来访问记录集。RecordSet 对象能方便的实现对记录的添加、修改和删除操作。
在使用这3个对象的时候,需要定义与之对应的3个智能指针,分别是:_ConnectionPtr, _CommandPtr, _RecordsetPtr. 然后调用他们的 CreateInstance 方法实例化,从而创建这3个对象的实例。
VC++ 中ADO 数据库开发的基本流程,它的基本步骤如下:
1. 引入ADO动态链接库
ADO不是MFC的基本类,该类打包在msado15.dll文件中,必须使用预编译指令 #import 语句将其引入
StdAfx.h 文件一般包含在所有的文件里,因此可以在此文件中引入ADO动态链接库。
// #import "C:\Program Files\common files\system\ado\msado15.dll" no_namespace rename("EOF","adoEOF") //XP系统
#import "C:\Program Files\common files\msado15.dll" no_namespace rename("EOF","adoEOF") //win7系统 msado.dll自己下载放入路径下的
2. 初始化OLE/COM库环境
ADO库是一组COM动态库,这意味着应用程序在调用ADO之前,必须初始化OLE/COM库环境,在MFC应用程序里,一个比较好的方法在实在应用程序主类的初始化函数里 初始化OLE/COM库 环境。
如InitInstance() 或构造函数里。
::CoInitialize(NULL);
或者
if(!AfxOleInit()){
AfxMessageBox("OLE初始化失败!");
}
3. 用Connection 对象连接数据库
try
{
::CoInitialize(NULL);
hbr=m_pConnection.CreateInstance(__uuidof(Connection));
m_pConnection->CursorLocation = adUseClient;
ConnectString.Format("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=%s",sPath);
//创建数据库的连接
hbr=m_pConnection->Open((_bstr_t)ConnectString,"","",adModeUnknown);hbr=m_pCommand.CreateInstance(__uuidof(Command));
m_pCommand->ActiveConnection = m_pConnection;
hbr=m_pRecordset.CreateInstance(__uuidof(Recordset));
}
catch (_com_error e)
{
Serror.Format("数据库连接失败:%s",e.ErrorMessage());
AfxMessageBox(Serror);
}
上述代码中,使用了try catch来处理COM异常,如不处理,ADO的异常可能是程序崩溃,所以一定要捕捉_com_error异常。
_ConnectionPtr智能指针Open方法的原型:
Open(_bstr_t ConnectionString, _bstr_t UserID, _bstr_t Password, long Options)
各个参数的含义如下:
ConnectionString是一个包含连接信息的字符串,UserID是访问数据库的用户名,Password是访问数据库的密码。
如果在连接字符串ConnectionString中包含了数据库的用户名和密码,则UserID, Password 值可以为空。
Options是可选参数,可以是如下几个常量:
adModeUnknown缺省,当前的许可权未设置
adModeRead 只读
adModeWrite 只写
adModeReadWrite 可以读写
adModeShareDenyRead 阻止其它Connection 对象以读权限打开连接
adModeShareDenyWrite 阻止其它Connection 对象以写权限打开连接
adModeShareExclusive 阻止其它Connection 对象打开连接
adModeShareDenyNone 阻止其它程序或对象以任何权限建立连接
4. 利用建立好的连接,打开记录,通过Connection, Command 对象执行SQL命令,或利用 Recordset 对象去得结果记录集进行查询、处理等数据操作。
strSql.Format("select * from 表);
m_pRecordset->Open(_bstr_t(strSql), m_pConnection.GetInterfacePtr(),
adOpenDynamic,
adLockOptimistic,
adCmdText);
RecordCount=m_pRecordset->GetRecordCount();
如添加记录的函数m_pRecordset->PutCollect(_variant_t("字段名"),_variant_t(添加值));
对记录的操作可以有下面几种方法:
1) Connection对象的Execute方法
_ConnectionPtr智能指针Execute方法的原型:
Execute(_bstr_t CommandText, VARIANT* RecordAffected, long Options)
其中CommandText 是命令字符串,通常是SQL命令;
RecordsAffected 是操作完成后所影响的行数;
Options表示 CommandText 中内容的类型,可以取下列值之一:
adCmdText 表示 是文本命令
adCmdTable 表示 是一个表名
adCmdProc 表示 是一个存储过程
adCmdUnknown 表示 未知
通常使用Connection 对象的Execute 方法来执行一条不返回任何结果的SQL语句,如执行一个存储过程:
Cstring strSql;
strSql.Format(“INSERTINTO table(NAME,AGE) VALUES(‘JACK’,24)”);
m_pConnection->Execute(_bstr_t(strSql),&RecordsAffected, adCmdText);
2)Command 对象的Execute 方法
Command 返回一个记录集。 它提供了一个种简单的方法来执行返回记录集的存储过程和SQL语句。在使用Command 接口时,可以利用全局 Connection 接口,也可以Command接口里直接使用连接串。如果只执行一次 或几次数据访问操作,后者是比较好的选择。
但是如果你要频繁的访问数据库,并要返回很多记录集,那么,应该使用全局Connection 接口创建一个数据连接,然后使用Command 接口执行SQL语句。
下面一段代码使用了全局的 Connection 接口执行一个删除过程:
_CommandPtrm_pCommand;
m_pCommand.CreateInstance(__uuidof(Command));
//将建立的连接赋值给它
m_pCommand->ActiveConnection=m_pConnection;
m_pCommand->CommandText=”deleteform table where name=’jack’”;
m_pCommand->Execute(NULL,NULL, adCmdText);
在使用命令对象 实现数据库的操作之前,需要定义一个_CommandPtr类型的指针,然后调用CreateInstance方法实例化。设置活动连接 ActiveConnection 是之指向 已经打开的数据库连接,
m_pCommand->ActiveConnection= m_pConnection;
然后设置sql语句,最后调用Execute 方法实现数据库的操作。
3)Recordset 对象的Open 方法
Recordset 对象 对记录集提供了更多的控制功能,如记录锁定、游标控制等。 同Command对象一样,它不一定 要使用一个已经创建的数据连接,可以用一个连接串 代替连接指针 赋值给Recordset 的connection 成员变量,让它自己创建数据连接。
如果你要使用多个记录集,最好的方法是同Command 对象一样,使用已经创建了数据连接的全局接口ConnectionPtr,然后使用Recordset执行 存储过程 和SQL语句。
下面的一段代码使用了全局的Connection 接口执行一个查询过程:
_RecordsetPtrm_pRecordset;
m_pRecordset.CreateInstance(_uuidof(Recordset));
m_pRecordset->Open(_bstr_t(“SELECT* FROM table WHERE name=’jack’”),
_variant_t((IDispatch*)m_pConnection,true),
adOpenStatic,
adLockOptimistic,
adCmdText );
用Open函数打开记录集,该函数原型为:
HRESULTRecordset15::Open(const _variant_t& Source,
const _variant_t& ActiveConnection,
enum CursorTypeEnum CursorType,
enum LockTypeEnum LockType,
long Options)
参数说明:
Source 是数据库查询字符串
ActiveConnection 是已经建立好的连接(我们需要用Connection 对象指针来构造一个_variant_t对象)
CursorType 光标类型,它是枚举CursorTypeEnum中的一个值
LockType 是数据库的锁定类型,它是枚举LockTypeEnum中的一个值
Options 指定Source的类型:
adCmdText 表示 是文本命令
adCmdTable 表示 是一个表名
adCmdProc 表示 是一个存储过程
adCmdUnknown 表示 未知
5. 使用完毕后关闭连接释放对象。
主程序退出时,需要断开和释放与数据库的连接。这项工作可以在应用程序的析构函数中或OnClose函数中完成。
m_pRecordset->Update();
m_pRecordset->Close();
m_pRecordset = NULL;
if(m_pConnection->State) //如果已经打开了连接则关闭它
{
m_pConnection->Close(); //断开与数据库的连接
m_pConnection.Release(); //释放与数据库的连接
}
m_pConnection= NULL;
m_pRecordset = NULL;
if(m_pConnection->State)
{
m_pConnection->Close();
}
m_pConnection= NULL;