⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 20.4 在 vc中利用ado访问数据库.txt

📁 网上第一本以TXT格式的VC++深入详解孙鑫的书.全文全以TXT格式,并每一章节都分了目录,清晰易读
💻 TXT
字号:
20.4 在 vc中利用ADO访问数据库
下面介绍在 VC中利用 ADO访问数据库的实现。首先新建一个基于对话框的应用程序,工程取名为: Ado,并删除自动创建的程序对话框资源中默认存在的静态文本控件。然后在该对话框资源上摆放一个列表框和一个按钮控件,并修改后者的属性,将其 ID设置为 IDC_BTN_QUERY, Caption设置为"查询"。新建的对话框资源如图 20 .3 2所示。
在 VC中利用 ADO访问数据库时,首先需要导入 ADO库(即先前在 VB中导入 Ado对象时所看到的动态链接库: msado15.dll)。本例在 Ado程序的预编译头文件=时afx.h中导入该库,方法是利用 import指令将此动态链接库导入,具体代码如下所示。
图 20 .3 2 本例使用的对话框资源
#import "C:\program Files\Common Files\System\ado\msado15.dll" no_narnespace rename (" EOF" , "rsEOF" ) 
上述代码中使用了 no namespace关键字, namespace就是命名空间。我们平时经常说"北京的中关村",这里"北京"就是"中关村"的命名空间。如果不用命名空间,即只说"中关村",那么如果全国只有北京有一个中关村时,大家都知道所说的中关村就是指北京的中关村。但是如果天津也有一个中关村,那么我们在北京和天津以外的地方说中关村时,就要加上命名空间,指定是北京的还是天津的中关村。本例中我们不需要命名空间,主要是为了访问方便,在程序中可以直接访问 ADO提供的 Connection、 Command和 Recordset 
-这三个 COM接口。
上述代码的最后还利用 rename将 EOF改为 rsEOF。前面己经提过, EOF表示记录集的结尾,因为文件也是以 EOF为结尾的,为了避免冲突,在导入 ADO库时,需要将 EOF改为 rsEOF。实际上,至于将其改为什么名字,读者可以根据自己的习惯来定。
导入 ADO库之后,可以编译 Ado程序,这时编译器会给出下面这样的一条警告,在 VC中利用 ADO库访问数据库时都会存在这一警告,对程序并没有影响,可以不用理会。 
d:\vc++深入编程 \chapter20 \ado\ado\debug\msado15.tlh(407) : warning C4146: unary minus operator applied to unsigned type , result still unsigned 
然后,找到 Ado工程所在的目录,在其 Debug目录下可以看到编译器为我们产生了两个文件: msado15.tlh和 rnsado15.tli。读者可以将 msado15.tlh看作是一个头文件,把 msado15.tli看作是一个源文件。应注意的是,这两个文件是在导入 ADO库后,编译器在编译时自动生成的,利用 ADO技术访问数据库时并不需要为工程导入这两个文件。
现在,就可以在"查询"按钮的单击消息响应函数中利用 ADO对象访问数据库了,具体代码如例 20-25所示。
例 20-25 
void CAdoDlg : :OnBtnQuery() 
// TODO: Add your control notification handler code here 
Coinitialize (NULL) ; 

_ConnectionPtr pConn(__uuidof(Connection)) ; 
6. _RecordsetPtr pRst (__uuidof(Recordset)) ; 
7. pConn->ConnectionString=" Provider=SQLOLEDB. 1; 
Password=sa; Persist Security ; Info= True ; User ID=sa ;Initial Catalog=pubs"; 
8. pConn->Open( "" ,"","" ,adConnectUnspecified); 
. 9. pRst=pConn->Execute("select * from authors" , NULL , adCmdText); 
10. while ( ! pRst->rsEOF) 

11. { 


12 . ((CListBox*)GetDlgItem(IDC_LIST1) ) ->AddString ( (_bstr_t) pRst->GetCollect ( " au_lnane")) ; 

13 . pRst->MoveNext(); 

14. } 

15. pRst->Close(); 

16. pConn->Close() ; 

17. pRst.Release(); 

18. pConn . Release(); 

19. CoUninitialize() ; 

20. } 


前面已经介绍过, OLEDB是基于 COM技术编写的, ADO是基于 OLEDB的,它实际上是一个 OLEDB的用户程序, ADO本身也是一个 COM组件。 COM组件在使用时,需要初始化 COM库,这需要调用 CoInitialize函数来实现,该函数有一个参数,该参数是保留的,直接传递 NULL即可。同时,在访问完 COM库后,程序还需要调用 CoUninitialize函数卸载 COM库。
在上述如例 20-25所示代码中用到了 ConnectionP位类型,这是一个智能指针,在 msado15.tlh文件中可以看到该类型的定义。
一COM_SMARTPTR_TYPEDEF(一.Connection,一_uuidof(_Connection)) ; 
_COM_SMARTPTR_TYPEDEF宏定义了一ConnectionP位智能指针类型,允许用户访问 ADO Connection对象。这个智能指针实际上就是一个类,在此类中重载了指向操作符(-抖,当然它还重载了许多其他操作符。在如例 20-25所示代码中,我们利用这个智能指针类定义了一个 ADO Connection对象: pConn,同时使用关键字_uuidof获取 ADO Connection 接口的全局惟一标识符 CGUID),对 pConn对象进行初始化。
l提示:在 msado15以件中, ;ff._COM_SMARTPTR_TYPEDEF宏中使用 
_uuidof关键字时,其参数 (_Connection)前面有下划线,但在 VC程序中不
需要书写该下划线,直接书写 Connection即可。

接下来,如例 20-25所示代码按照同样的方法,再产生一个记录集智能指针对象: pRst。然后就可以利用智能指针对象去访问该对象的属性和万法了。首先,为数据库连接对象的连接字符串赋值,可以复制先前 VB程序中己创建的连接字符串并粘贴即可。然后调 
用连接对象的Open方法打开与数据库的连接。需要注意的是,在VB程序中. Open函数

的参数是可选的,可以不用赋值,但在VC程序中必须为它们明确赋值,该函数的定义在 

msado15.tli文件中。 

inl.ne HRESULT _Connection15::0pen ( _bstr_t ConnectionString, _bstr_t 

UserID,  _bstr_t Password,  long Options ) {  
可以看到 Open函数有四个参数,其中连接字符串( ConnectionStrin挝、用户  ID( UserID) 
和密码字符串 CPassword)的类型是-bstLt,这是一个  COM支持类,封装了  BSTR数据 

类型。 -bw-t类型提供了多种构造方法,其中的一种构造函数的定义如下所示。 

_bstr_t( const char* s2 ) throw( _COffi_error ); 

可见该类型的构造函数有一个 const char*类型的参数,所以对上述Open函数来说,只需要为-bWJ类型的参数传递一个常量字符串就可以了,这里可以直接为这些参数传递一个空的字符串,因为它们已经在连接字符串中设置好了,但注意不能为它们传递NULL值。上述 Open函数的第四个参数是一个枚举值,其取值有两个: adAsyncConnect和 adConnectUnspecified。如果是前者,表示异步打开连接:如果是后者,表明同步打开连接。本例使用后者,同步打开连接。在这里顺便提一下,如果在ASP中利用ADO访问数据库,它将不能识别adAsyncConnect和adConnectUnspecified这些符号,因此只能用这些符号所代表的数值一1 C adConnectU nspecified)或16 CadAsyncConnect)来代替。
接下来,如例 20-25所示代码调用连接对象的Execute方法。该函数的第一个参数是命令文本,即SQL语旬,本例将从authors表中查询所有数据:第二个参数是一个参数指针,本例将它设置为 NULL;第三个参数用来设置命令文件的类型,可以将它设置为 adCmdText类型。
当得到记录集数据后,可以利用一个循环来获取每一条记录的数据,井将它添加到列表框中。从记录集中取数据时,可以利用GetCollect方法,该方法有一个 -varimLt类型的参数,该类型也是一个 COM支持类。这里可以直接给该参数传递一个常量字符串: " au_lname" ,用来获取作者的lastname字段信息。另外, GetCol1ect函数返回值的类型是 
variant t类型,而CListBox的 AddString函数需要的是constchar*类型的值,因此必须进行一个强制转换,先将GetCollect函数的返回值转换为-bmJ类型,又因为后者重载了 const char*操作符,所以,得到的_bstct类型的数值会自动转换为constchar*类型的数值。
在获取记录集数据的循环的最后,一定要记得调用记录集对象的MoveNext函数,以便让游标向下移动。
当数据操作完成之后,调用记录集对象的Close方法关闭记录集,然后再调用连接对象的 Close方法关闭连接。最后需要释放智能指针在COM接口上的引用计数,即分别调用记录集对象和连接对象的Release方法,该方法将释放相应COM接口的引用计数。
国际:智能指针的一个特点:在访问其他方法和属性时都是用箭头指向操

作符(-> ),但在调用 Release方法释放引用计数时必须使用点操作符(.)。 

Build并运行Ado程序,单击【查询】按钮,列表框中出现数据。如图20.33所示。
图20.33 VC中利用ADO访问数据库的程序运行结果

同样也可以利用记录集智能指针对象直接执行 SQL查询语旬以获取记录集数据,我们将如例20-25所示CAdoDlg类的OnBtnQuery函数中第9行代码注释起来,然后在其后添加下面这条语句。 
pRst->Open("select * frorn authors' , _variant_t((工Dispatch*)pConn) , 
adOpen乌rnarnic, adLockOptirnistic, adCrndText) ; 
未完先到此
该 Open函数的第一个参数就是 SQL语句:第二个参数设置活动的连接,类型是 Variant,因此需要进行强制类型转换:第三个参数是游标的类型,本例选择adOpenDynatIùc类型;第四个参数是锁的类型,本例选择adLockOptimistic类型:最后一个参数设置命令类型,本例将其指定为adCmdText类型。
读者可以试着运行这时的Ado程序,将会发现与先前的实现方式得到的结果是一样的。

当然,与前面在 VB中实现一样,在 VC中同样还能利用  Command智能指针对象来 
访问数据库。这时CAdoDlg类的 OnBtnQuery函数的代码如例 20-26所示。  
'Wtl20-26  


vo工d CAdoDlg : : OnBtnQuery() 
11 TODO: Add your control not工f工cation handler code here 
Colnitialize(NULL) : 
_ConnectionPtr pConn(一_uuidof(Connection)) : 
一RecordsetPtr pRst(一_uuidof(Recordset)) : 
_CornrnandPtr pCmd(一_uuidof(Cornrnand) ): 

pConn->ConnectionString="Provider=SQLOLEDB.l:Password=sa:Pers工st Security Info= True:User ID=sa:工nitial Catalog=pubs ": pConn->Open("" , "", "", adConnectUnspecified): 
IlpRst=pCo口n->Execute( "select * from authors" , NULL , adCmdText): IlpRst->Open("select * frorn authors",_variant_t((工Dispatch*)pConn) , 11 adOpenDynarnic,ad工,ockOptimistic,adCmdText): 
pCrnd->put_ActiveConnection(_variant_t((IDispatch*)pConn)); pCrnd->CornrnandText="select * frorn authors" : pRst=pCmd->Execute(NULL , NULL , adCmdText) : while(!pRst->rsEOF) 
{ 
((CListBox*)GetDlgltern(IDC_LIST1) )->AddString( 

5遗传‘ I 767 
第 20 

(_bstr_t)pRst->GetCollect("au_lnarne") ); pRst->MoveNext(); 
. 
pRst->Close() ; pConn->Close(); pCrnd.Release() ; pRst. Release () ; pConn.Release(); CoUninitialize() ; 
这时,首先按照同样的方法构造一个 Command智能指针对象: pCmd,然后调用其 puCActive Connection方法设置活动连接,接下来设置 Command对象的命令文本属性 (CommandText),本例直接将它设置为一条 SQL语句,然后调用 Command对象的 Execute方法,并将执行结果赋给记录集对象: pRst。同样,在使用完数据之后,调用 Command对象的 Release方法释放相应 COM接口上的引用计数。
读者可以测试这时的 Ado程序,将会看到与前两种实现方式相同的结果。
以上就是在 VC中利用 ADO技术访问数据库的程序实现,共介绍了三种方法,从中可以看到,无论采用哪种方法访问数据,最终数据都是放到记录集对象中。同时也看到,在 VC中利用 ADO访问数据库比较麻烦,而在 VB中是很方便的。所以在利用 ADO访问数据库时,最好使用 VB来编写。细心的读者可能会注意到,在 MSDN中提供的与 ADO相
F 关的文档,都是针对 VB的,没有针对 VC的。因为在 VC中对 ADO的访问确实比较麻烦。

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -