在现代软件开发中,数据库技术被越来越广泛应用,很多项目都存在着大量的数据需要存储,通常都会采用数据库来存储这些数据。最初,数据库厂商推出一个新的数据库产品时,相应的,他会为程序员提供一套访问该数据库的接口,即API。不同的数据库厂商提供的访问接口是不一样的,这样在使用一个新的数据库时,就要学习一套新的API,当然这就加大了开发数据库的难度,也不利于数据库在软件开发过程中的应用。因此,后来Microsoft就推出了一些标准的访问数据库的技术。

      这一部分主要介绍ADO访问数据库的情况,对于其它技术,可以自行查阅相应书籍,ADO中有以下3个核心对象。

@Connection对象

      Connection对象表示到数据库的链接,它管理应用程序和数据库之间的通信,下面的2个对象都有一个ActiveConnection属性,该属性用来引用Connection对象。

@Command对象

      Command对象用来 处理 重复执行的查询,或处理 需要检查 在存储过程中的输出或返回值 的查询。

@RecordSet对象

      RecordSet对象用来保存数据,存放查询的结果,这些结果由数据的行(记录)和列(字段)组成。每一列都存放在RecordSet的Fields集合中的一个Field对象中。

第一步:

      在VC中利用ADO访问数据库时,首先需要导入ADO库。在程序的预编译头文件stdAfx.h中导入该库,方法是利用import指令将此动态链接库导入,具体代码如下:#import "c:/program files/common files/system/ado/msado15.dll" no_namespace rename("EOF","rsEOF"),代码中使用了no_namespace关键字,namespace是命名空间,本例中不需要命名空间,主要是为了访问方便,在程序中可以直接访问ADO提供的Connection、Command、RecordSet这3个COM接口。最后利用rename将EOF改为rsEOF。EOF表示 记录集 的结尾,因为文件也是以EOF为结尾的,为了避免冲突,在导入ADO库时,需要将EOF改为rsEOF。至于将其改为什么名字,可以根据自己的习惯来定。

      在导入ADO库之后,编译程序,会出现一条警告,在VC中利用ADO访问数据库时都会存在这一警告,对程序并没有影响,可以不用理会。编译之后,在Debug目录下,可以看到编译器为我们产生了两个文件,msado15.tlh和msado15.tli。可以将msado15.tlh看作是一个头文件,msado15.tli看作是一个源文件,这两个文件是在导入ADO库之后,编译器在编译的时候自动生成的,利用ADO技术访问数据库并不需要为工程导入这两个文件。

第二步:

      为需要访问数据库的类添加2个成员变量,_RecordsetPtr m_pRs(数据集对象);_ConnectionPtr m_pConn;(数据库链接对象)   接着在程序初始化的时候初始化这2个对象

 

[cpp] view plaincopy
 
  1. CoInitialize(NULL);  
  2.     try  
  3.     {  
  4.         //初始化数据库连接对象  
  5.         m_pConn.CreateInstance("ADODB.Connection");  
  6.         m_pRs.CreateInstance(__uuidof(Recordset));//这里必须初始化。  
  7.         //定义数据库连接字符串,打开本地Access库  
  8.         m_pConn->ConnectionString="Provider=Microsoft.ACE.OLEDB.12.0;Data Source=DBS.mdb;Persist Security Info=False";  
  9.         //打开数据库连接  
  10.         m_pConn->Open("","","",adConnectUnspecified);  
  11.           
  12.     }  
  13.     catch(_com_error &e)  
  14.     {  
  15.         ::CoUninitialize();  
  16.         ::AfxMessageBox(e.ErrorMessage());  
  17.         return FALSE;  
  18.           
  19.     }  

 

 

COM组件在使用时,需要初始化COM库,这就需要调用CoInitialize(NULL);函数来实现,该函数有一个参数,该参数是保留的,直接传递NULL即可,同时在访问完COM库之后,程序需要调用CoUninitialize();函数卸载COM库。

      接着,初始化 数据链接对象 和 数据集对象。在初始化这两个对象时,利用__uuidof获取ADO Connection和ADO RecordSet对象的全局唯一标识符(GUID)。对m_pConn对象进行初始化。

      然后,利用智能指针对象去访问该对象的属性和方法了。首先,为数据库链接对象的链接字符串赋值。然后调用链接对象的Open方法打开与数据库的链接。关于链接字符串的获得:不必死记硬背,可以利用VB开发环境来得到链接字符串,P756。

      接下来就可以利用链接对象的Execute方法来从数据库获得数据了。

 

[cpp] view plaincopy
 
  1. void CMy_DbsDlg::OnBtnQue()   
  2. {     
  3.     try  
  4.     {  
  5.         CString strsql;  
  6.         strsql.Format("SELECT * FROM RoomStandard");  
  7.         HRESULT hr=m_pRs->Open(_variant_t(strsql),(m_pConn.GetInterfacePtr()),adOpenStatic,adLockOptimistic,adCmdText);  
  8.         //m_pRs=m_pConn->Execute((_bstr_t)strsql,NULL,adCmdText);  
  9.         _variant_t vFieldValue;  
  10.         if(SUCCEEDED(hr))  
  11.         {  
  12.             //m_pRs->MoveFirst();//移至第一条记录---------默认指针在第一条记录上  
  13.             m_list.DeleteAllItems();  
  14.             int i=0,n=0;  
  15.             while(!(m_pRs->GetrsEOF()))//while(!m_pRs->rsEOF)  
  16.             {  
  17.                 int k=0;  
  18.                 vFieldValue=m_pRs->GetCollect(_variant_t(long(k)));  
  19.                 if(vFieldValue.vt!=NULL)  
  20.                 {                 
  21.                     k=1;  
  22.                     m_list.InsertItem(n,_bstr_t(vFieldValue));//插入列表控件  
  23.                     for(;k<9;k++)                      
  24.                     {  
  25.                         vFieldValue=m_pRs->GetCollect(_variant_t(long(k)));  
  26.                         if(vFieldValue.vt!=NULL)  
  27.                         {  
  28.                             m_list.SetItemText(n,k,_bstr_t(vFieldValue));  
  29.                         }  
  30.                     }  
  31.                 }  
  32.                 n++;//记录数加1;  
  33.                 m_pRs->MoveNext();  
  34.             }  
  35.             m_pRs->Close();  
  36.         }  
  37.     }  
  38.     catch(_com_error e)  
  39.     {  
  40.         AfxMessageBox(e.ErrorMessage());  
  41.         AfxMessageBox((LPCTSTR)(e.Description()));  
  42.     }  
  43.     ///////////////////////////////////////////  
  44.     //这里要判断一下记录是不是打开的,要以防不正常的情况下记录没有关闭!  
  45.     if(m_pRs)  
  46.     {  
  47.         if (m_pRs->State)  
  48.         {         
  49.             m_pRs->Close();  
  50.         }  
  51.     }  
  52. }  

 

 

      当数据操作完成之后,调用记录集对象的Close方法关闭记录集,最后调用链接对象的Close方法关闭链接。然后还需要释放智能指针在COM接口上的引用计数,即分别调用记录集对象和链接对象的Release方法,该方法将释放相应COM接口的引用计数。智能指针有一个特点,在访问其它属性和方法时,都是用->操作符,但在调用Release方法释放引用计数时,必须使用.操作符。