ADO中打開一個連接:
pConnection->ConnectionString = "這里的字符串有下面四種寫法"; //對連接字符串賦值
pConnection->Open(ConnectionString,"","",adModeUnknown); //連接數據庫
第二三個參數分別為用戶的ID與密碼,因為在連接字符串ConnectionCstring中已經設置好了,這里可以為空。
第四個參數可以取下面兩個參數:adAsyncConnect,異步打開數據庫,在ASP中直接用16。 adConnectUnspecified,同步打開數據庫,在ASP中直接用-1。
ConnectionString根據不同的數據源,分別對應不同的寫法(要記下來很困難,可以在VB中利用ADO控件先連接好,再將其拷貝在VC中,這樣不容易出錯)
1)訪問Access 2000
"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=databaseName;User ID=userName;Password=userPassWord"
2)訪問ODBC數據
"Provider=MADASQL;DSN=dsnName;UID=userName;PWD=userPassword;"
3)訪問Oracle數據庫
“Provider=MSDAORA;Data Sourse=serverName;User ID=userName;Password=userPassword;"
4)訪問MS SQL數據庫
"Provider=SQLOLEDB,Data Source=serverName;Initial Catalog=databaseName;User ID=userName;Password=userPassword;"
使用ADO開發應用程序有兩種方法,一種是直接在應用程序中使用ADO數據控件,該方法最簡單,無需編寫一行代碼即可實現對數據庫的訪問,另一種方法是直接使用ADO對象實現對數據庫的操作,該方法較復雜,但可以讓程序員更深入的控制數據庫。
一.使用ActiveX控件建立應用程序
該方法需要兩個ActiveX控件:Microsoft ADO Data Control ,version 6.0(OLE DB)和Microsoft ADO DataGrid Control ,version 6.0(OLE DB)。下面我們就使用這兩個控件,建立一個訪問SQL Server 7.0數據庫的應用程序,步驟如下:
1.啟動VC6.0,使用MFC AppWizard建立一個單文檔應用程序,命為AdoCtl,在Step1到Step 5中使用缺設置,直接按Next即可,在Step 6中,選擇視圖類的基類為CFormView,然后按Finish,按OK,生成應用程序框架;
2.在應用程序的ResourceView中,刪除IDD_ADOCTL_FORM對話框中自動生成的靜態文本,然后在該對話框的編輯窗口中擊鼠標右鍵,在彈出的快捷菜單中選擇Insert ActiveX Control...命令;
3.在接下來的Insert ActiveX Control對話框中選擇Microsoft ADO Data Control ,version 6.0(OLE DB),按OK,就可以將該控件插入到對話框中。
4.重復步驟2、3,在對話框中插入Microsoft ADO DataGrid Control ,version 6.0(OLE DB)控件;
5.選中Data控件,擊右鍵,設置該控件的屬性;
6.選擇Control頁面,該屬性頁要連接的數據源,其中提供了3種連接數據源的方法:
a.使用數據連接文件(Use Data Link File);
b.使用ODBC數據源(Use ODBC Data Source Name);
c.使用連接字符串(Use Connection String).。
在本程序中,我們使用連接字符串,連接SQL Server7.0數據庫。連接字符串中包含了程序與數據源的連接信息,其形式為Argument=Value,每個連接字符串可以包含多個Argument=Value表達式,不同的表達式之間以分號間隔,如訪問SFJ55.MDB數據庫的連接字符串可以寫成如下形式:
Provider=Microsoft.Jet.OLEDB.4.0;Data Source=e:\\sfj55.mdb
ADO支持如下的四種連接字符串的屬性設置:
選擇Use Connection String選項,按Build...鈕,在數據鏈接屬性對話框中選擇OLE DB Provider(OLE DB提供者),此處我們選擇Microsoft OLE DB Provider for SQL Server,按下一步;
7.在連接屬性頁中輸入服務器名稱,筆者使用NT工作站,名稱為BUILDER,SQL Server裝在本機,故此處服務器名稱為BUILDER,再選擇使用Windows NT集成安全設置,在服務器上選擇數據庫,筆者選擇DcProduct,這是一個存放生產明細的數據庫。測試連接成功后按確定。也可以選擇SQL Server 7.0自帶的其他數據庫和數據表。
8.選擇Data控件屬性的RecordSource屬性頁,其中Command Type 中有4個選項:
對於SQL語句和數據表名,使用過Access97的讀者一定很熟悉,至於存儲過程的有關信息請參考SQL Server的有關書籍。此處我們選擇2-adCmdTable,表名選擇[SFJ55-27-00-000MX](注意在表名兩邊加中括號),關閉屬性對話框。Data控件屬性設置完畢;
9.選擇DataGrid控件,擊右鍵,設置該控件的屬性;
10.選擇All屬性頁,設置DataSource屬性,設置為Data控件的ID號,即IDC_ADODC1,關閉屬性對話框;
11.編譯並運行應用程序,即可在DataGrid控件中顯示數據表SFJ55-27-00-000MX中的數據。
到此為止,我們在VC6.0中使用ADO技術建立的最簡單的應用程序已經完成,整個過程中沒有編寫一行代碼。只是該程序只能瀏覽和修改數據,不能對記錄進行添加和刪除。如果想增加充足添加和刪除記錄的功能,在DataGrid控件的All屬性頁中,設置AllowAddNew和AllowDelete屬性為TRUE。
這中方法盡管簡單,但是對數據庫的訪問效率較低,使用起來也不靈活,程序員對數據庫的控制較少,不能最大限度的發揮ADO技術高速靈活的特點。下面通過一個實例來介紹在VC6.0中使用ADO對象訪問SQL Server數據庫。
二.使用ADO對象建立數據庫應用程序
在VC中使用過DAO的讀者對於CDaoWorkspace,CDaoDatabase,CDaoRecordset,CDaoTableDef等MFC類應該非常熟悉,然而,遺憾的是VC中並沒有提供有關ADO對象的類,那么我們將怎樣使用ADO對象呢?實際上,這可以通過在應用程序中使用預編譯指令#import來引入相關類的指針。在使用ADO對象之前必須首先在程序中加入如下的代碼:
#define INITGUID //定義有關的變量
#import "C:\program files\common files\system\ado\msado15.dll"rename_namespace("ADOCG")rename("EOF","EndOfFile") //引入動態鏈接庫
using namespace ADOCG;
#include "icrsint.h" //包含頭文件
以上代碼在程序的運行過程中將產生名為msado15.tlh的頭文件,該頭文件中定義了一些有用的智能指針,以下是該文件關於智能指針定義的一段代碼:
//
// Smart pointer typedef declarations
//
......
_COM_SMARTPTR_TYPEDEF(Properties, __uuidof(Properties));
_COM_SMARTPTR_TYPEDEF(Property, __uuidof(Property));
_COM_SMARTPTR_TYPEDEF(Error, __uuidof(Error));
_COM_SMARTPTR_TYPEDEF(Errors, __uuidof(Errors));
_COM_SMARTPTR_TYPEDEF(_Connection, __uuidof(_Connection));
_COM_SMARTPTR_TYPEDEF(_Recordset, __uuidof(_Recordset));
_COM_SMARTPTR_TYPEDEF(Fields, __uuidof(Fields));
_COM_SMARTPTR_TYPEDEF(Field, __uuidof(Field));
_COM_SMARTPTR_TYPEDEF(_Parameter, __uuidof(_Parameter));
_COM_SMARTPTR_TYPEDEF(Parameters, __uuidof(Parameters));
_COM_SMARTPTR_TYPEDEF(_Command, __uuidof(_Command));
......
這是基於ADO的支持類_com_ptr_t的一些指針的定義,其中宏_COM_SMARTPTR_TYPEDEF()在VC6.0頭文件COMDEF.H中定義。
下面是我們經常使用的幾個智能指針:
_ConnectionPtr 連接對象指針
_RecordsetPtr 記錄集對象指針
_ParameterPtr 參數對象指針
_CommandPtr 命令對象指針
FieldPtr 域對象指針
PropertyPtr 屬性對象指針
ErrorPtr 錯誤對象指針
下面在一個程序實例中說明這些指針的用法,程序訪問的數據庫為SQL Server 7.0中自帶的NothWind,數據表名為Employees,這里只訪問EmployeeID,LastName,FirstName,Title等4個字段:
步驟1.啟動VC6.0,使用MFC AppWizard建立一個單文檔應用程序,命為AdoCls,在Step1到Step 5中使用缺設置,直接按Next即可,在Step 6中,選擇視圖類的基類為CFormView,然后按Finish,按OK,生成應用程序框架,在應用程序的ResourceView中,刪除IDD_ADOCLS_FORM對話框中自動生成的靜態文本;
步驟2.新建一個文本文件,並在其中輸入如下內容,然后將其保存為MyData.h,再將其添加到AdoCls工程中(菜單命令:Project\Add To Project\Files...),輸入內容如下:
//MyData.h
#define INITGUID
#import "C:\program files\common files\system\ado\msado15.dll"rename_namespace("ADOCG")rename("EOF","EndOfFile")
using namespace ADOCG;
#include "icrsint.h"
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
class CMyRecord : public CADORecordBinding
{
BEGIN_ADO_BINDING(CMyRecord ) //開始數據捆綁
ADO_FIXED_LENGTH_ENTRY(1,adInteger,m_id,lid,TRUE);
ADO_VARIABLE_LENGTH_ENTRY2(2,adVarChar,m_lastname,sizeof(m_lastname),llastname,TRUE)
ADO_VARIABLE_LENGTH_ENTRY2(3,adVarChar,m_firstname,sizeof(m_firstname),lfirstname,TRUE)
ADO_VARIABLE_LENGTH_ENTRY2(4,adVarChar,m_title,sizeof(m_title),ltitle,TRUE)
END_ADO_BINDING() //結束數據捆綁
public:
long m_id;
ULONG lid;
char m_lastname[20];
ULONG llastname;
char m_firstname[10];
ULONG lfirstname;
char m_title[30];
ULONG ltitle;
};
在MyData.h頭文件中定義了一個CMyRecord類,該類的基類必須是CADORecordBinding,且沒有構造函數和析構函數,只有一組用於數據捆綁和映射的宏和一組變量。其中以“m_”開頭的4個變量分別對應數據表Employees中EmployeeID,LastName,FirstName,Title等4個字段,它們將用於存取這4個字段的實際值,以“l”開頭的4個ULONG類型的變量是對應字段的狀態值,用於判斷數據的捆綁是否成功,后面的程序代碼中將看到其應用。用於數據捆綁和映射的宏在頭文件icrsint.h中定義,數據的捆綁和映射主要用到如下的幾個宏:
(1). BEGIN_ADO_BINDING ()和 END_ADO_BINDING()
BEGIN_ADO_BINDING()宏的參數是用戶自定義的用於數據捆綁的記錄集類,本例中為CMyRecord。END_ADO_BINDING()宏不帶參數。
(2). ADO_FIXED_LENGTH_ENTRY()宏,該宏用於數據庫中所有長度固定的字段,如Date/Time,BOOL,int,或定長的字符型字段。有兩個版本:
(1)#define ADO_FIXED_LENGTH_ENTRY(Ordinal,DataType,Buffer,Status,Modify);
(2)#define ADO_FIXED_LENGTH_ENTRY2(Ordinal,DataType,Buffer,,Modify);
(3). ADO_NUMERIC_ENTRY(),用於數值型字段。也有兩個版本:
(1)#define ADO_NUMERIC_ENTRY(Ordinal,DataType,Buffer,Precision,Scale,Status,Modify);
(2)#define ADO_NUMERIC_ENTRY(Ordinal,DataType,Buffer,Precision,Scale,Modify);
(4).ADO_VARIABLE_LENGTH_ENTRY(),有四個版本:
(1)#define ADO_VARIABLE_LENGTH_ENTRY(Ordinal,DataType,Buffer,Size,Status,Length,Modify);
(2)#define ADO_VARIABLE_LENGTH_ENTRY2(Ordinal,DataType,Buffer,Size,Status,Modify);
(3)#define ADO_VARIABLE_LENGTH_ENTRY3(Ordinal,DataType,Buffer,Size,Length,Modify);
(4)#define ADO_VARIABLE_LENGTH_ENTRY4(Ordinal,DataType,Buffer,Size,Modify);
Ordinal 被訪問的記錄集中的字段的序號,數據表Employees中EmployeeID,LastName,FirstName,Title等4個字段的序號分別為1、2、3、4;
DataType 字段數據類型,見頭文件msado15.tlh(在程序的運行過程中將產生);
Buffer 字段中的值所要映射到的變量
Status 被映射字段的狀態值
Modify 是否允許修改
Precision 字段值的精度(數值型)
Scale 字段值的數值范圍(數值型)
Size 變長度字段值的長度(如:字符串)
步驟3.進入ResourceView,在IDD_ADOCLS_FORM對話框中添加如下圖所示幾個控件:
4個文本框控件對應的變量分別是m_id,m_firstname,m_lastname,m_title,這4個變量均屬於CAdoClsView類。
步驟4.在CAdoClsDoc類頭文件包含MyRecord.h,並在其中添加如下幾個私有成員變量:
private:
CMyRecord m_rsRecSet;
_RecordsetPtr m_pRs;
IADORecordBinding * m_piAdoRecordBinding;
CString m_strCmdText;
CString m_strConnection;
HRESULT hr;
步驟5.在文檔類構造函數中初始化COM環境和建立與數據庫的連接,在析構函數中清除COM環境和釋放有關變量。在CAdoClsDoc類構造函數中添加如下內容:
::CoInitialize(NULL);//初始化COM環境
m_piAdoRecordBinding=NULL;
m_strConnection=_T("Provider=SQLOLEDB.1;Integrated Security=SSPI;Persist Security Info=False;Initial Catalog=Northwind;Data Source=BUILDER");
m_strCmdText=_T("select EmployeeID,LastName,FirstName,Title from Employees");
//創建對象實例
m_pRs.CreateInstance(__uuidof(Recordset));
//利用智能指針打開記錄集
m_pRs->Open(LPCTSTR(m_strCmdText),LPCTSTR(m_strConnection),adOpenDynamic,adLockOptimistic,adCmdText);
hr=m_pRs->QueryInterface(__uuidof(IADORecordBinding),(LPVOID*)&m_piAdoRecordBinding);
hr=m_piAdoRecordBinding->BindToRecordset(&m_rsRecSet);//與CMyRecord記錄類捆綁
//此處,變量hr僅僅是用來判函數的調用是否成功,如果成功則hr等於0,否則hr小於0。
在CAdoClsDoc類析構函數中添加如下內容:
//在析構函數中關閉與數據源的連接,釋放有關變量
if(m_pRs)m_pRs->Close();
if(m_piAdoRecordBinding)m_piAdoRecordBinding->Release();
m_pRs=NULL;
CoUninitialize();//清除COM環境
注意:在ADO中,獲得記錄集的方法有大約3種:1.通過連接對象的Execute()方法;2.通過命令對象的Execute()方法(但是,該命令對象必須首先與連接對象建立關聯pCmd->ActiveConnection=);3.直接建立並打開記錄集對象(在這種方法里面,其Open()函數中的ActiveConnection參數既可以是連接對象指針,又可以是連接字符串)。因此,使用ADO技術訪問數據庫的數據是非常自由的,不象DAO,必須先建立Database對象,然后再建立Recordset對象。我們這里采用第3中方法,這種方法只適用與簡單的應用中,如果在應用中需要訪問多哥數據源,則必須采用1和2兩種方法顯式的建立連接,以加快訪問速度。
步驟6.在文檔類中添加記錄集的Move類函數,MoveFirst()、MovePrevious()、MoveNext()、MoveLast()、AddNew()、CreateBlankRecord():
void CAdoClsDoc::MoveFirst()
{
if(m_pRs->Supports(adUpdate))
hr=m_piAdoRecordBinding->Update(&m_rsRecSet);
m_pRs->MoveFirst();
}
void CAdoClsDoc::MovePrevious()
{
if(!m_pRs->BOF)
{
hr=m_piAdoRecordBinding->Update(&m_rsRecSet);
m_pRs->MovePrevious();
}
}
void CAdoClsDoc::MoveNext()
{
if(!m_pRs->EndOfFile){
hr=m_piAdoRecordBinding->Update(&m_rsRecSet);
m_pRs->MoveNext();
}
}
void CAdoClsDoc::MoveLast()
{
hr=m_piAdoRecordBinding->Update(&m_rsRecSet);
m_pRs->MoveLast();
}
步驟7.在CAdoClsDoc類中添加GetMyRecord()函數:
CMyRecord * CAdoClsDoc::GetMyRecord()
{
return(&m_rsRecSet);
}
步驟8.在void CAdoClsView::OnInitialUpdate()函數中添加如下代碼:
{.......
RefreshBoundData();}
步驟9.在CAdoClsView類中添加RefreshBoundData()函數及其實現代碼:
void CAdoClsView::RefreshBoundData()
{
CMyRecord * pRs;
pRs=GetDocument()->GetMyRecord();
m_firstname=adFldOK==pRs->lfirstname?pRs->m_firstname:"";
m_lastname=adFldOK==pRs->llastname?pRs->m_lastname:"";
m_title=adFldOK==pRs->ltitle?pRs->m_title:"";
UpdateData(FALSE);
}
步驟10.在CAdoClsView類中添加UpdateBoundData()函數及其實現代碼:
void CAdoClsView::UpdateBoundData()
{
CMyRecord * pRs;
pRs=GetDocument()->GetMyRecord();
UpdateData(TRUE);
if(pRs->m_id!=m_id)
pRs->m_id=m_id;
if(pRs->m_firstname!=m_firstname)
strcpy(pRs->m_firstname,LPCTSTR(m_firstname));
if(pRs->m_lastname != m_lastname)
strcpy(pRs->m_lastname,LPCTSTR(m_lastname));
if(pRs->m_title !=m_title)
strcpy(pRs->m_title ,LPCTSTR(m_title));
}
步驟10.在CAdoClsView類中添加IDD_ADOCLS_FORM對話框中四個按鈕對應的消息映射函數:
void CAdoClsView::OnButtonFirst()
{ UpdateBoundData();
GetDocument()->MoveFirst ();
RefreshBoundData();
}
void CAdoClsView::OnButtonLast()
{ UpdateBoundData();
GetDocument()->MoveLast ();
RefreshBoundData();
}
void CAdoClsView::OnButtonNext()
{ UpdateBoundData();
GetDocument()->MoveNext ();
RefreshBoundData();
}
void CAdoClsView::OnButtonPrevious()
{ UpdateBoundData();
GetDocument()->MovePrevious ();
RefreshBoundData();
}
步驟11.編譯運行該應用程序,即可實現對數據庫的瀏覽。
使用ADO在VC6中建立數據庫應用程序,至此結束,關於這一方法以及本程序例子,作以下幾點說明:
1.運行上面的程序,試着改變數據庫中的某個列的數值,讀者將會發現,在數據記錄的移動時,數據庫並沒有被更新。這是因為本程序所涉及到的四個字段中,其中有一個標識列,EmployeeID,標識列具有自動增長的特性,用戶不能更新,否則將出錯,這時,語句hr=m_piAdoRecordBinding->Update(&m_rsRecSet);將返回一個負值,即hr<0,讀者可以SQL Server 7中的Enterprise Manager打開NothWind數據庫,修改其中的數據表Employees,在該表的設計視圖中將其EmployeeID所在行的Identify復選框取消,然后保存。這時用戶即可實現對數據庫的更新。在調試時注意一下語句hr=m_piAdoRecordBinding->Update(&m_rsRecSet),hr將等於0。
2.CMyRecord類的基類是CADORecordBinding,IADORecordBinding 是CADORecordBinding類的一個COM接口,它也是記錄集類CADORecordBinding的一部分,用戶可以通過該接口實現數據的捆綁、更新和添加,它對應3個(僅有3個)函數:BindToRecordset()、AddNew()和Update(),這三個函數可以參見頭文件icrsint.h。其中BindToRecordset()和Update()我們已經使用過,AddNew()的用法與Update()很相似,首先,將MyRecord類中各個數值變量(以m_開頭)賦初值,然后調用m_piAdoRecordBinding->AddNew(&m_rsRecSet)和m_pRs->MoveLast()(將記錄指針移到新添加的空白記錄處),即可實現記錄的添加功能。
3.在宏ADO_VARIABLE_LENGTH_ENTRY2(Ordinal,DataType,Buffer,Size,Status,Modify);中,第一個參數Ordinal指的是在當前記錄集中字段的位置,而不是原數據表中該字段的位置。如本程序中的LastName字段,在程序中所要訪問的記錄集中的位置是2,如果將記錄集改為:“select LastName,FirstName,Title from Employees”,則LastName的位置將為1,Ordinal=1。
4.如果讀者不喜歡數據捆綁的方式訪問數據庫,ADO提供了對記錄集中單個域進行訪問的方法,如以下代碼可以更新當前記錄中的FirstName字段:
_variant_t vFld,vValue;
vFld.SetString("FirstName");
vValue.SetString("Rose Tom");
m_pRs->Update(vFld,vValue);
以下代碼可以取得FirstName字段值:
_variant_t vValue;
CString strValue;
vValue=m_pRs->GetCollect(_variant_t ("FirstName"));
vValue.ChangeType(VT_BSTR);
strValue=vValue.bstrVal;
這種直接訪問字段值的方法很靈活,缺點是編程人員必須頻繁的調用ChangeType函數進行數據類型的轉換。