在现代软件开发中,数据库技术被越来越广泛应用,很多项目都存在着大量的数据需要存储,通常都会采用数据库来存储这些数据。最初,数据库厂商推出一个新的数据库产品时,相应的,他会为程序员提供一套访问该数据库的接口,即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个对象
- CoInitialize(NULL);
- try
- {
- //初始化数据库连接对象
- m_pConn.CreateInstance("ADODB.Connection");
- m_pRs.CreateInstance(__uuidof(Recordset));//这里必须初始化。
- //定义数据库连接字符串,打开本地Access库
- m_pConn->ConnectionString="Provider=Microsoft.ACE.OLEDB.12.0;Data Source=DBS.mdb;Persist Security Info=False";
- //打开数据库连接
- m_pConn->Open("","","",adConnectUnspecified);
- }
- catch(_com_error &e)
- {
- ::CoUninitialize();
- ::AfxMessageBox(e.ErrorMessage());
- return FALSE;
- }
COM组件在使用时,需要初始化COM库,这就需要调用CoInitialize(NULL);函数来实现,该函数有一个参数,该参数是保留的,直接传递NULL即可,同时在访问完COM库之后,程序需要调用CoUninitialize();函数卸载COM库。
接着,初始化 数据链接对象 和 数据集对象。在初始化这两个对象时,利用__uuidof获取ADO Connection和ADO RecordSet对象的全局唯一标识符(GUID)。对m_pConn对象进行初始化。
然后,利用智能指针对象去访问该对象的属性和方法了。首先,为数据库链接对象的链接字符串赋值。然后调用链接对象的Open方法打开与数据库的链接。关于链接字符串的获得:不必死记硬背,可以利用VB开发环境来得到链接字符串,P756。
接下来就可以利用链接对象的Execute方法来从数据库获得数据了。
- void CMy_DbsDlg::OnBtnQue()
- {
- try
- {
- CString strsql;
- strsql.Format("SELECT * FROM RoomStandard");
- HRESULT hr=m_pRs->Open(_variant_t(strsql),(m_pConn.GetInterfacePtr()),adOpenStatic,adLockOptimistic,adCmdText);
- //m_pRs=m_pConn->Execute((_bstr_t)strsql,NULL,adCmdText);
- _variant_t vFieldValue;
- if(SUCCEEDED(hr))
- {
- //m_pRs->MoveFirst();//移至第一条记录---------默认指针在第一条记录上
- m_list.DeleteAllItems();
- int i=0,n=0;
- while(!(m_pRs->GetrsEOF()))//while(!m_pRs->rsEOF)
- {
- int k=0;
- vFieldValue=m_pRs->GetCollect(_variant_t(long(k)));
- if(vFieldValue.vt!=NULL)
- {
- k=1;
- m_list.InsertItem(n,_bstr_t(vFieldValue));//插入列表控件
- for(;k<9;k++)
- {
- vFieldValue=m_pRs->GetCollect(_variant_t(long(k)));
- if(vFieldValue.vt!=NULL)
- {
- m_list.SetItemText(n,k,_bstr_t(vFieldValue));
- }
- }
- }
- n++;//记录数加1;
- m_pRs->MoveNext();
- }
- m_pRs->Close();
- }
- }
- catch(_com_error e)
- {
- AfxMessageBox(e.ErrorMessage());
- AfxMessageBox((LPCTSTR)(e.Description()));
- }
- ///////////////////////////////////////////
- //这里要判断一下记录是不是打开的,要以防不正常的情况下记录没有关闭!
- if(m_pRs)
- {
- if (m_pRs->State)
- {
- m_pRs->Close();
- }
- }
- }
当数据操作完成之后,调用记录集对象的Close方法关闭记录集,最后调用链接对象的Close方法关闭链接。然后还需要释放智能指针在COM接口上的引用计数,即分别调用记录集对象和链接对象的Release方法,该方法将释放相应COM接口的引用计数。智能指针有一个特点,在访问其它属性和方法时,都是用->操作符,但在调用Release方法释放引用计数时,必须使用.操作符。