ADO在C++中的使用

最近程序中用到读写数据库,看了些例子,查了番MSDN,下面把详细步骤写出来,以备忘,或与同行共勉。

读写数据库的技术很多,现在多用ADOADOCOM方式提供,所以它的很多行为遵循COM规范。首先,要引入ADOCOM文件,它的位置一般在"C:/Program Files/Common Files/System/ado/msado15.dll"

1. 引入ADO

打开预编译头文件StdAfx.h,写上引入声明:

#import "C:/Program Files/Common Files/System/ado/msado15.dll" no_namespace rename("EOF","adoEOF")

解释一下上句:no_namespace是指忽略命名空间,rename则是把ADO中的EOF重命名为adoEOF。命成什么名字无所谓,但注意声明中的名字要和代码中的名字一致。

2. 初始化

ADO写代码前,要将COM初始化。常用手段是在代码前后加上CoInitialize(NULL)CoUninitialize()。也可以用AfxOleInit()来初始化COM库。

3. 三个核心对象

ADO3个核心对象是连接对象(_Connection)、命令对象(_Command)和记录集对象(_RecordSet)。其中连接对象是任何操作必须的。很多操作3个核心对象都可以完成。要实例化它们并使用它们提供的方法,不得不说到它们是一种智能指针(Smart Pointer)。在初始化或释放等操作时,它们是一个对象,用点操作符,其他大部分操作则使用“->”操作符。

4. 实例化

       _ConnectionPtr pConn(__uuidof(Connection));

       _RecordsetPtr pRec(__uuidof(Recordset));

       _CommandPtr pCmd(__uuidof(Command));

如果上面不加参数,则需加上:

              pConn.CreateInstance("ADODB.Connection");

              pRec.CreateInstance("ADODB.Recordset");

              pCmd.CreateInstance("ADODB.Command");

5. 连接数据库

连接数据库一般采取字符串连接。这个字符串的获取方法用了“不能说的秘密”,即任意新建一个txt文件,重命名为.x.udl。然后双击此文件,将出现“数据库连接属性”窗口。第一个标签页“提供程序”列出了所有数据库引擎,Access, SQL Server Oracle等,选择后点下一步跳至第二个标签页“连接”,选择服务器名称栏可以填上服务器的IP地址,本机则可不填或填点号;填上数据库用户名和密码后就可以选择数据库了。点“测试连接”按钮,成功。确定。用记事本打开x.udl。将会看到它生成的连接字符串。如下:

"Provider=SQLOLEDB.1;Persist Security Info=False;User ID=sa;Password=123;Initial Catalog=cfdata"

此连接串中,Persist Security Info属性为True时表示在建立连接后仍然保存密码,一般取False即可。IDPassword属性只有在上述数据库属性对话框中勾选“允许保存密码”时才会有。自己可以手工添加。Cfdata是我的数据库名。

C++中连接代码如下:

              pConn->ConnectionString="Provider=SQLOLEDB.1;Persist Security Info=False;User ID=sa;Password=123;Initial Catalog=cfdata";

6. 示例

有些数据库操作_Connection一个就能完全搞定。如update语句。因为它不需要返回的结果。如下:

              pConn->ConnectionString="Provider=SQLOLEDB.1;Persist Security Info=False;User ID=sa;Password=123;Initial Catalog=cfdata";

              pConn->Open("","","",adConnectUnspecified);   //打开连接。此处参数均已在上述字符串声明,故可为空

              CString strSQL="update table1 set name=’Richard’ where id=1";

_pConn->Execute(_bstr_t(strSQL),NULL,adCmdText);

这里涉及强制类型转换。COM中的数据类型和常规(MFC)类型一般都有对应,但需要转换。如上面的_bstr_tCString。至于应该转换成什么类型,看VC环境中的提示即可(这里推荐大家加装Visual Assitant,使提示功能更完善)

也有些操作需要返回记录集,如select语句。这里就至少需要_Connection_Recordset两种核心对象,也可以用_Command执行之。下面展示同一操作用3种对象分别实现的代码。

(1)连接对象

              CString strSQL="select * from table1";     //方法1

              pRec=pConn->Execute(_bstr_t(strSQL),NULL,adCmdText);

 

(2)记录集对象

              CString strSQL="select * from table1";           //方法2

pRec->Open(_variant_t(strSQL),(_variant_t)( (IDispatch*)pConn),adOpenDynamic,adLockOptimistic,adCmdText);

其中第二个参数(_variant_t)( (IDispatch*)pConn)指明活动连接,数据类型转换比较复杂,_variant_t是参数要求的类型,IDispath*则是_variant_t可强制转换类型类型。也可用下句:

pConnGetInterfacePtr();

(3) 命令对象

              CString strSQL="select * from table1";         //方法3

              pCmd->put_ActiveConnection((_variant_t)((IDispatch*)pConn)); 

              pCmd->CommandText=_bstr_t(strSQL);

              pRec=pCmd->Execute(NULL,NULL,adCmdText);

7. 数据使用

取得记录集后,将其中数据取出。用一个ListBox读取其中name字段数据。代码如下:

              while(!pRec->adoEOF)

              {

              //_bstr_t类型可以视作COM类型字符串和MFC类型字符串之间的桥梁

                     CString str=LPSTR(_bstr_t(pRec->GetCollect("name")));

                     ((CListBox*)GetDlgItem(IDC_LIST1))->AddString(str);

                     pRec->MoveNext();

              }

上述代码中用到了adoEOF,要注意直接拷贝第三方代码时可能会被重命名为rsEOF等,此时则需作相应更改。另外,while循环中的MoveNext()也不要忘了,否则它就成了死循环了。字段值的获取及转换也可用下面方法:

                     _variant_t var=pRec->GetCollect("name");

                     var.ChangeType(VT_BSTR);

                     CString str=var.bstrVal;

8. 关闭与释放

用完相应对象后,需要关闭并释放之,代码如下:

              pRec->Close();

              pConn->Close();

              pRec.Release();

              pCmd.Release();

              pConn.Release();

9. 错误捕获

数据库操作难免出现错误,连接串错误,SQL语句错误,或返回NULL你却硬要向表里塞(此错误可以在取出后用var.vt!=VT_NULL判断),所以我们需要把它们放到try…catch段中。ADO在捕获到错误后会抛出_com_error类型异常,我们可以这样做:

       try

       {

              pConn->ConnectionString="Provider=SQLOLEDB.1;Persist Security Info=False;User ID=sa;Password=123;Initial Catalog=cfdata";

              pConn->Open("","","",adConnectUnspecified);

   …………   //代码省略

    }

       catch(_com_error& e)

       {

              AfxMessageBox(e.ErrorMessage());

              AfxMessageBox(e.Description());

       }

        这里有个疑惑,在捕获错误后,e.ErrorMessage()e.Description()中放着不同信息,有时前者说得清晰,有的后者说的清晰,搞不清楚,索性就都加上吧。最后,可以再加个catch(…),毕竟ADO之外的地方也可能发生错误。

这里,我还犯过一个错误,被它整了N久。我把_com_error& e写成了_com_error* e后面也对应改成->操作符,而且编译通过,结果一运行程序就崩溃,而且它不告诉我在哪出错,因为这时的错误是_com_error这时却对着_com_error*来捕获当然捕不到。这里&只是一个引用,写不写无所谓,*是万万不可地。(网上书上很多大师级代码都是用了*,误导啊)

10. 其他接口

ADO中除了3个核心对象外,我们还应了解FieldsPtrFieldPtrStreamPtr等接口。例如上述示例中,我们可以用FieldsPtrGetCount()方法获取其字段个数,用FieldPtr来接收具体字段等。二进制数据如图像文件等则会用到StreamPtr。就写到这里。欢迎加入我们的VC群713035,和众多C++程序员共同进步。(全文完)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值