Visual C++ ADO資料庫程式設計入門
ado[@more@]摘要 本文簡要介紹了在VC++ 6.0中使用 ADO進行客戶端資料庫程式設計的基本步驟,以及常見問題的解決方法,可供入門級的參考之用。
關鍵字 ADO VC++ 資料庫程式設計
ADO 是目前在Windows環境中比較流行的客戶端資料庫程式設計技術。ADO是建立在OLE DB底層技術之上的高階程式設計介面,因而它兼具有強大的資料處理功能(處理各種不同型別的資料來源、分散式的資料處理等等)和極其簡單、易用的程式設計介面,因而得到了廣泛的應用。而且按微軟公司的意圖,OLE DB和ADO將逐步取代 ODBC和DAO。現在介紹ADO各種應用的文章和書籍有很多,本文著重站在初學者的角度,簡要探討一下在VC++中使用ADO程式設計時的一些問題。我們希望閱讀本文之前,您對ADO技術的基本原理有一些瞭解。
一、在VC++中使用ADO程式設計
ADO實際上就是由一組Automation物件構成的元件,因此可以象使用其它任何Automation物件一樣使用ADO。ADO中最重要的物件有三個:Connection、Command和Recordset,它們分別表示連線物件、命令物件和記錄集物件。如果您熟悉使用MFC中的ODBC類(CDatabase、CRecordset)程式設計,那麼學習ADO程式設計就十分容易了。
使用ADO程式設計時可以採用以下三種方法之一:
1、使用預處理指令#import
但要注意不能放在stdAfx.h檔案的開頭,而應該放在所有include指令的後面。否則在編譯時會出錯。
程式在編譯過程中,VC++會讀出msado15.dll中的型別庫資訊,自動產生兩個該型別庫的標頭檔案和實現檔案msado15.tlh和msado15.tli(在您的Debug或Release目錄下)。在這兩個檔案裡定義了ADO的所有物件和方法,以及一些列舉型的常量等。我們的程式只要直接呼叫這些方法就行了,與使用MFC中的COleDispatchDriver類呼叫Automation物件十分類似。
2、使用MFC中的CIDispatchDriver
就是透過讀取msado15.dll中的型別庫資訊,建立一個COleDispatchDriver類的派生類,然後透過它呼叫ADO物件。
3、直接用COM提供的API
如使用如下程式碼:
其中icrsint.h檔案包含了VC++擴充套件的一些預處理指令、宏等的定義,用於COM程式設計時使用。
2、定義_ConnectionPtr型變數,並建立資料庫連線
建立了與資料庫伺服器的連線後,才能進行其他有關資料庫的訪問和操作。ADO使用Connection物件來建立與資料庫伺服器的連線,所以它相當於MFC中的CDatabase類。和CDatabase類一樣,呼叫Connection物件的Open方法即可建立與伺服器的連線。
資料型別 _ConnectionPtr實際上就是由類别範本_com_ptr_t而得到的一個具體的例項類,其定義可以到msado15.tlh、comdef.h 和comip.h這三個檔案中找到。在msado15.tlh中有:
經宏擴充套件後就得到了_ConnectionPtr類。_ConnectionPtr類封裝了Connection物件的Idispatch介面指標,及一些必要的操作。我們就是透過這個指標來操縱Connection物件。類似地,後面用到的_CommandPtr和_RecordsetPtr型別也是這樣得到的,它們分別表示命令物件指標和記錄集物件的指標。
(1)、連線到MS SQL Server
注意連線字串的格式,提供正確的連線字串是成功連線到資料庫伺服器的第一步,有關連線字串的詳細資訊參見微軟MSDN Library光碟。
本例連線字串中的server_name,database_name,user_name和password在程式設計時都應該替換成實際的內容。
注意Connection物件的Open方法中的連線字串引數必須是BSTR或_bstr_t型別。另外,本例是直接透過OLE DB Provider建立連線,所以無需建立資料來源。
(2)、透過ODBC Driver連線到Database Server連線字串格式與直接用ODBC程式設計時的差不多:
此時與ODBC程式設計一樣,必須先建立資料來源。
3、定義_RecordsetPtr型變數,並開啟資料集
定義_RecordsetPtr型變數,然後透過它呼叫Recordset物件的Open方法,即可開啟一個資料集。所以Recordset物件與MFC中的CRecordset類類似,它也有當前記錄、當前記錄指標的概念。如:
Recordset物件的Open方法非常重要,它的第一個引數可以是一個SQL語句、一個表的名字或一個命令物件等等;第二個引數就是前面建立的連線物件的指標。此外,用Connection和Command物件的Execute方法也能得到記錄集,但是隻讀的。 (待續1-2摘自ITDB資料庫)
本例中的name和age都是欄位名,讀取的欄位值分別儲存在sName和cAge變數內。例中的Fields是Recordset物件的容器,GetItem方法返回的是Field物件,而Value則是Field物件的一個屬性(即該欄位的值)。透過此例,應掌握操縱物件屬性的方法。例如,要獲得Field 物件的Value屬性的值可以直接用屬性名Value來引用它(如上例),但也可以呼叫Get方法,例如:
從此例還可以看到,判斷是否到達記錄集的末尾,使用記錄集的adoEOF屬性,其值若為真即到了結尾,反之則未到。判斷是否到達記錄集開頭,則可用BOF屬性。
另外,讀取資料還有一個方法,就是定義一個繫結的類,然後透過繫結的變數得到欄位值(詳見後面的介紹)。
5、修改資料
方法一:
改變了Value屬性的值,即改變了欄位的值。
方法二:
方法三:就是用定義繫結類的方法(詳見後面的介紹)。
6、新增記錄
新記錄新增成功後,即自動成為當前記錄。AddNew方法有兩種形式,一個含有引數,而另一個則不帶引數。
方法一(不帶引數):
這種方法弄完了還要呼叫Update()。
方法二(帶引數):
這種方法不需要呼叫Update,因為新增後,ADO會自動呼叫它。此方法主要是使用SafeArray挺麻煩。
方法三:就是用定義繫結類的方法(詳見後面的介紹)。
關鍵字 ADO VC++ 資料庫程式設計
ADO 是目前在Windows環境中比較流行的客戶端資料庫程式設計技術。ADO是建立在OLE DB底層技術之上的高階程式設計介面,因而它兼具有強大的資料處理功能(處理各種不同型別的資料來源、分散式的資料處理等等)和極其簡單、易用的程式設計介面,因而得到了廣泛的應用。而且按微軟公司的意圖,OLE DB和ADO將逐步取代 ODBC和DAO。現在介紹ADO各種應用的文章和書籍有很多,本文著重站在初學者的角度,簡要探討一下在VC++中使用ADO程式設計時的一些問題。我們希望閱讀本文之前,您對ADO技術的基本原理有一些瞭解。
一、在VC++中使用ADO程式設計
ADO實際上就是由一組Automation物件構成的元件,因此可以象使用其它任何Automation物件一樣使用ADO。ADO中最重要的物件有三個:Connection、Command和Recordset,它們分別表示連線物件、命令物件和記錄集物件。如果您熟悉使用MFC中的ODBC類(CDatabase、CRecordset)程式設計,那麼學習ADO程式設計就十分容易了。
使用ADO程式設計時可以採用以下三種方法之一:
1、使用預處理指令#import
#import "C:Program FilesCommon FilesSystemADOmsado15.dll" no_namespace rename("EOF", "EndOfFile") |
但要注意不能放在stdAfx.h檔案的開頭,而應該放在所有include指令的後面。否則在編譯時會出錯。
程式在編譯過程中,VC++會讀出msado15.dll中的型別庫資訊,自動產生兩個該型別庫的標頭檔案和實現檔案msado15.tlh和msado15.tli(在您的Debug或Release目錄下)。在這兩個檔案裡定義了ADO的所有物件和方法,以及一些列舉型的常量等。我們的程式只要直接呼叫這些方法就行了,與使用MFC中的COleDispatchDriver類呼叫Automation物件十分類似。
2、使用MFC中的CIDispatchDriver
就是透過讀取msado15.dll中的型別庫資訊,建立一個COleDispatchDriver類的派生類,然後透過它呼叫ADO物件。
3、直接用COM提供的API
如使用如下程式碼:
CLSID clsid; HRESULT hr = ::CLSIDFromProgID(L"ADODB.Connection", &clsid); if(FAILED(hr)) {...} ::CoCreateInstance(clsid, NULL, CLSCTX_SERVER, IID_IDispatch, (void **) &pDispatch); if(FAILED(hr)) {...} |
以上三種方法,第一和第二種類似,可能第一種好用一些,第三種程式設計可能最麻煩。但可能第三種方法也是效率最高的,程式的尺寸也最小,並且對ADO的控制能力也最強。
據微軟資料介紹,第一種方法不支援方法呼叫中的預設引數,當然第二種方法也是這樣,但第三種就不是這樣了。採用第三種方法的水平也最高。當你需要繞過ADO而直接呼叫OLE DB底層的方法時,就一定要使用第三種方法了。
ADO程式設計的關鍵,就是熟練地運用ADO提供的各種物件(object)、方法(method)、屬性(property)和容器(collection)。另外,如果是在MS SQL或Oracle等大型資料庫上程式設計,還要能熟練使用SQL語言。
二、使用#import方法的程式設計步驟 這裡建議您使用#import的方法,因為它易學、易用,程式碼也比較簡潔。
1、 新增#import指令
開啟stdafx.h檔案,將下列內容新增到所有的include指令之後:
#include #import "C:Program FilesCommon FilesSystemADOmsado15.dll" no_namespace rename("EOF", "adoEOF") |
其中icrsint.h檔案包含了VC++擴充套件的一些預處理指令、宏等的定義,用於COM程式設計時使用。
2、定義_ConnectionPtr型變數,並建立資料庫連線
建立了與資料庫伺服器的連線後,才能進行其他有關資料庫的訪問和操作。ADO使用Connection物件來建立與資料庫伺服器的連線,所以它相當於MFC中的CDatabase類。和CDatabase類一樣,呼叫Connection物件的Open方法即可建立與伺服器的連線。
資料型別 _ConnectionPtr實際上就是由類别範本_com_ptr_t而得到的一個具體的例項類,其定義可以到msado15.tlh、comdef.h 和comip.h這三個檔案中找到。在msado15.tlh中有:
_COM_SMARTPTR_TYPEDEF(_Collection, __uuidof(_Collection)); |
經宏擴充套件後就得到了_ConnectionPtr類。_ConnectionPtr類封裝了Connection物件的Idispatch介面指標,及一些必要的操作。我們就是透過這個指標來操縱Connection物件。類似地,後面用到的_CommandPtr和_RecordsetPtr型別也是這樣得到的,它們分別表示命令物件指標和記錄集物件的指標。
(1)、連線到MS SQL Server
注意連線字串的格式,提供正確的連線字串是成功連線到資料庫伺服器的第一步,有關連線字串的詳細資訊參見微軟MSDN Library光碟。
本例連線字串中的server_name,database_name,user_name和password在程式設計時都應該替換成實際的內容。
_ConnectionPtr pMyConnect=NULL; HRESULT hr=pMyConnect.CreateInstance(__uuidof(Connection))); if(FAILED(hr))return; _bstr_t strConnect="Provider=SQLOLEDB; Server=server_name;" "Database=database_name; uid=user_name; pwd=password;"; //connecting to the database server now: try{pMyConnect->Open(strConnect,"","",NULL);} catch (_com_error &e) { ::MessageBox(NULL,e.Description(),"警告",MB_OK │ MB_ICONWARNING); } |
注意Connection物件的Open方法中的連線字串引數必須是BSTR或_bstr_t型別。另外,本例是直接透過OLE DB Provider建立連線,所以無需建立資料來源。
(2)、透過ODBC Driver連線到Database Server連線字串格式與直接用ODBC程式設計時的差不多:
_bstr_t strConnect="DSN=datasource_name; Database=database_name; uid=user_name; pwd=password;"; |
此時與ODBC程式設計一樣,必須先建立資料來源。
3、定義_RecordsetPtr型變數,並開啟資料集
定義_RecordsetPtr型變數,然後透過它呼叫Recordset物件的Open方法,即可開啟一個資料集。所以Recordset物件與MFC中的CRecordset類類似,它也有當前記錄、當前記錄指標的概念。如:
_RecordsetPtr m_pRecordset; if(!FAILED(m_pRecordset.CreateInstance( __uuidof( Recordset ))) { m_pDoc->m_initialized=FALSE; return; } try{ m_pRecordset->Open(_variant_t("mytable"), _variant_t((IDispatch *)pMyConnect,true), adOpenKeyset, adLockOptimistic, adCmdTable); } catch (_com_error &e) { ::MessageBox(NULL,"無法開啟mytable表。","提示", MB_OK │ MB_ICONWARNING); } |
Recordset物件的Open方法非常重要,它的第一個引數可以是一個SQL語句、一個表的名字或一個命令物件等等;第二個引數就是前面建立的連線物件的指標。此外,用Connection和Command物件的Execute方法也能得到記錄集,但是隻讀的。 (待續1-2摘自ITDB資料庫)
4、讀取當前記錄的資料
我認為讀取資料的最方便的方法如下:
try{ m_pRecordset->MoveFirst(); while(m_pRecordset->adoEOF==VARIANT_FALSE) { //Retrieve column's value: CString sName=(char*)(_bstr_t)(m_pRecordset->Fields->GetItem (_variant_t("name"))->Value); short cAge=(short)(m_pRecordset->Fields->GetItem (_variant_t("age"))->Value); //Do something what you want to do: ...... m_pRecordset->MoveNext(); } }//try catch (_com_error &e) { CString str=(char*)e.Description(); ::MessageBox(NULL,str+"n又出毛病了。","提示", MB_OK │ MB_ICONWARNING); } |
本例中的name和age都是欄位名,讀取的欄位值分別儲存在sName和cAge變數內。例中的Fields是Recordset物件的容器,GetItem方法返回的是Field物件,而Value則是Field物件的一個屬性(即該欄位的值)。透過此例,應掌握操縱物件屬性的方法。例如,要獲得Field 物件的Value屬性的值可以直接用屬性名Value來引用它(如上例),但也可以呼叫Get方法,例如:
CString sName=(char*)(_bstr_t)(m_pRecordset->Fields->GetItem (_variant_t("name"))->GetValue()); |
從此例還可以看到,判斷是否到達記錄集的末尾,使用記錄集的adoEOF屬性,其值若為真即到了結尾,反之則未到。判斷是否到達記錄集開頭,則可用BOF屬性。
另外,讀取資料還有一個方法,就是定義一個繫結的類,然後透過繫結的變數得到欄位值(詳見後面的介紹)。
5、修改資料
方法一:
try{ m_pRecordset->MoveFirst(); while(m_pRecordset->adoEOF==VARIANT_FALSE) { m_pRecordset->Fields->GetItem (_variant_t("姓名"))->Value=_bstr_t("趙薇"); ...... m_pRecordset->Update(); m_pRecordset->MoveNext(); } }//try |
改變了Value屬性的值,即改變了欄位的值。
方法二:
m_pRecordset->Fields->GetItem (_variant_t("姓名"))->PutValue(_bstr_t("趙薇")); |
方法三:就是用定義繫結類的方法(詳見後面的介紹)。
6、新增記錄
新記錄新增成功後,即自動成為當前記錄。AddNew方法有兩種形式,一個含有引數,而另一個則不帶引數。
方法一(不帶引數):
// Add new record into this table: try{ if(!m_pRecordset->Supports(adAddNew)) return; m_pRecordset->AddNew(); m_pRecordset->Fields->GetItem (_variant_t("姓名"))->Value=_bstr_t("趙薇"); m_pRecordset->Fields->GetItem (_variant_t("性別"))->Value=_bstr_t("女"); m_pRecordset->Fields->GetItem (_variant_t("age"))->Value=_variant_t((short)20); m_pRecordset->Fields->GetItem (_variant_t("marry"))->Value=_bstr_t("未婚"); m_pRecordset->Update(); }//try catch (_com_error &e) { ::MessageBox(NULL, "又出毛病了。","提示",MB_OK │ MB_ICONWARNING); } |
這種方法弄完了還要呼叫Update()。
方法二(帶引數):
_variant_t varName[4],narValue[4]; varName[0] = L"姓名"; varName[1] = L"性別"; varName[2] = L"age"; varName[3] = L"marry"; narValue[0]=_bstr_t("趙薇"); narValue[1]=_bstr_t("女"); narValue[2]=_variant_t((short)20); narValue[3]=_bstr_t("未婚"); const int nCrit = sizeof varName / sizeof varName[0]; // Create SafeArray Bounds and initialize the array SAFEARRAYBOUND rgsaName[1],rgsaValue[1]; rgsaName[0].lLbound = 0; rgsaName[0].cElements = nCrit; SAFEARRAY *psaName = SafeArrayCreate( VT_VARIANT, 1, rgsaName ); rgsaValue[0].lLbound = 0; rgsaValue[0].cElements = nCrit; SAFEARRAY *psaValue = SafeArrayCreate( VT_VARIANT, 1, rgsaValue ); // Set the values for each element of the array HRESULT hr1=S_OK.hr2=S_OK; for( long i = 0 ; i < nCrit && SUCCEEDED( hr1 ) && SUCCEEDED( hr2 );i++) { hr1=SafeArrayPutElement(psaName, &i,&varName[i]); hr2=SafeArrayPutElement(psaValue, &i,&narValue[i]); } // Initialize and fill the SafeArray VARIANT vsaName,vsaValue; vsaName.vt = VT_VARIANT │ VT_ARRAY; vsaValue.vt = VT_VARIANT │ VT_ARRAY; V_ARRAY(&vsaName) = psaName;//&vsaName->parray=psaName; //see definition in oleauto.h file. V_ARRAY(&vsaValue) = psaValue; // Add a new record: m_pRecordset->AddNew(vsaName,vsaValue); |
這種方法不需要呼叫Update,因為新增後,ADO會自動呼叫它。此方法主要是使用SafeArray挺麻煩。
方法三:就是用定義繫結類的方法(詳見後面的介紹)。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10957369/viewspace-1002806/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- ADO資料庫程式設計入門(轉)資料庫程式設計
- 在Visual C++中用ADO進行資料庫程式設計 (轉)C++資料庫程式設計
- Go Web 程式設計入門--應用資料庫GoWeb程式設計資料庫
- 資料庫設計簡單入門資料庫
- ADO.NET入門教程之資料庫連線池資料庫
- C++入門程式設計----C++運算子(8)C++程式設計
- 理解 Visual C++ Extensions for ADO(轉)C++
- Visual C++/MFC入門教程C++
- 在C++Builder 5中使用ADO資料庫程式設計 (轉)C++UI資料庫程式設計
- 入門計劃->使用(C++庫)ifstream讀檔案資料 (轉)C++
- 入門計劃->使用(C++庫)ofstream寫檔案資料 (轉)C++
- ADO.NET 快速入門(十):過濾資料
- ORACLE入門之OLTP和DSS不同資料庫設計Oracle資料庫
- 利用ADO壓縮Access資料庫程式碼資料庫
- ant程式設計資料--非常簡單入門詳細程式設計
- C++併發程式設計框架Theron(3)——Theron入門C++程式設計框架
- 入門程式碼程式設計程式設計
- 怎樣用c/c++程式設計連線mysql資料庫?C++程式設計MySql資料庫
- 資料庫實驗八 資料庫程式設計資料庫程式設計
- 資料庫實驗五:資料庫程式設計資料庫程式設計
- Shell 程式設計入門程式設計
- shell程式設計入門程式設計
- MongoDB資料庫入門MongoDB資料庫
- 好程式設計師分享自學大資料入門乾貨程式設計師大資料
- Visual C++網路程式設計案例實戰pdfC++程式設計
- Visual C++ 6.0程式設計實現列印功能(轉)C++程式設計
- ADO程式設計應用 (轉)程式設計
- 【資料庫設計】資料庫的設計資料庫
- 程式設計和網路程式設計入門程式設計
- 遊戲程式設計入門指南遊戲程式設計
- Number 1 — 程式設計入門程式設計
- Python程式設計入門Python程式設計
- csh shell程式設計入門程式設計
- TCSHshell程式設計入門(轉)程式設計
- shell程式設計入門指南程式設計
- cache資料庫入門教程資料庫
- 程式設計入門——壘積木學程式設計程式設計
- ADO.NET連線資料庫資料庫