日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

ADO学习(一)基础理论

發布時間:2024/4/11 编程问答 41 豆豆
生活随笔 收集整理的這篇文章主要介紹了 ADO学习(一)基础理论 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.


ADO概述

ADOMicrosoft?ActiveXData?Object,是MicrosoftODBC之后,基于OLE?DB技術的一種數據庫操作技術,使您能夠編寫通過?OLE?DB提供者對在數據庫服務器中的數據進行訪問和操作的應用程序。ADOOLE?DB、數據庫之間的關系可以用下圖來表示:

其主要優點是易于使用、高速度、低內存支出和占用磁盤空間較少。ADO支持用于建立基于客戶端/服務器和?Web的應用程序的主要功能。

?

?

二、ADO初步認識

????????在此介紹的ADO編程技術都是基于C++的,要熟練掌握如何用ADO操作數據庫,首先對ADO技術得有個總體的了解,AD0主要由幾個對象組成:ConnectionCommandParamenterRecordersetFieldsErrorProperty對象,對數據庫的操作,都是通過這幾個對象來進行的,對象模型的關系圖如下:

?

·??????Connection對象

在數據庫應用里操作數據源都必須通過該對象,這是數據交換的環境。Connection對象代表了同數據源的一個會話,在客戶/服務器模型里,這個會話相當于同服務器的一次網絡連接。不同的數據提供者提供的該對象的集合、方法和屬性不同。

借助于Connection對象的集合、方法和屬性,可以使用OpenClose方法建立和釋放一個數據源連接。使用Execute方法可以執行一個數據操作命令,使用BeginTransCommitTransRollbackTrans方法可以啟動、提交和回滾一個處理事務。通過操作the?Errors?集合可以獲取和處理錯誤信息,操作CommandTimeout屬性可以設置連接的溢出時間,操作ConnectionString屬性可以設置連接的字符串,操作Mode屬性可以設置連接的模式,操作Provider屬性可以指定OLE?DB提供者。

·??????Command對象

Command對象是一個對數據源執行命令的定義,使用該對象可以查詢數據庫并返回一個Recordset對象,可以執行一個批量的數據操作,可以操作數據庫的結構。不同的數據提供者提供的該對象的集合、方法和屬性不同。

借助于Command對象的集合、方法和屬性,可以使用Parameters集合制定命令的參數,可以使用Execute方法執行一個查詢并將查詢結果返回到一個Recordset對象里,操作CommandText屬性可以為該對象指定一個命令的文本,操作CommandType屬性可以指定命令的類型,操作Prepared可以得知數據提供者是否準備好命令的執行,操作CommandTimeout屬性可以設置命令執行的溢出時間。

·??????Parameter對象

Parameter對象在Command對象中用于指定參數化查詢或者存儲過程的參數。大多數數據提供者支持參數化命令,這些命令往往是已經定義好了的,只是在執行過程中調整參數的內容。

借助于Parameter對象的集合、方法和屬性,可以通過設置Name屬性指定參數的名稱,通過設置Value屬性可以指定參數的值,通過設置AttributesDirectionPrecisionNumericScaleSizeType屬性可以指定參數的信息,通過執行AppendChunk方法可以將數據傳遞到參數里。

·??????Recordset對象

如果執行的命令是一個查詢并返回存放在表中的結果集,這些結果集將被保存在本地的存儲區里,Recordset對象是執行這種存儲的ADO對象。通過Recordset對象可以操縱來自數據提供者的數據,包括修改和更新行、插入和刪除行。

ADO定義了如表

光標類型

描述

adOpenDynamic

允許添加、修改和刪除記錄,支持所有方式的光標移動,其他用戶的修改可以在聯機以后仍然可見

adOpenKeyset

類似于adOpenDynamic光標,它支持所有類型的光標移動,但是建立連接以后其他用戶對記錄的添加不可見,其他用戶對記錄的刪除和對數據的修改是可見的。支持書簽操作

adOpenStatic

支持各種方式的光標移動,但是建立連接以后其他用戶的行添加、行刪除和數據修改都不可見,支持書簽操作

adOpenForwardOnly

只允許向前存取,而且在建立連接以后,其他用戶的行添加、行刪除和數據修改都不可見,支持書簽操作

ADO定義了如表

鎖定類型

描述

adLockReadOnly

(缺省)數據只讀

adLockPessimistic

鎖定操作的所有行,也稱為消極鎖定

adLockOptimistic

只在調用Update方法時鎖定操作的行,也稱為積極鎖定

adLockBatchOptimistic

在批量更新時使用該鎖定,也稱為積極批量鎖定

ADO定義了如表

光標服務位置

描述

adUseNone

不使用光標服務位置

adUseClient

使用客戶端光標

adUseServer

(缺省)使用數據服務端或者驅動提供端光標

借助于Recordset對象的集合、方法和屬性,可以通過設置CursorType屬性設置記錄集的光標類型,通過設置CursorLocation屬性可以指定光標位置,通過讀取BOFEOF屬性的值,獲知當前光標在記錄集里的位置是在最前或者最后,通過執行MoveFirstMoveLastMoveNextMovePrevious方法移動記錄集里的光標,通過執行Update方法可以更新數據修改,通過執行AddNew方法可以執行行插入操作,通過執行Delete方法可以刪除行。

·??????Field對象

Recordset對象的一個行由一個或者多個Fields對象組成,如果把一個Recordset對象看成一個二維網格表,那么Fields對象就是這些列。這些列里保存了列的名稱、數據類型和值,這些值是來自數據源的真正數據。為了修改數據源里的數據,必須首先修改Recordset對象各個行里Field對象里的值,最后Recordset對象將這些修改提交到數據源。

借助于Field對象的集合、方法和屬性,可以通過讀取Name屬性,獲知列的名稱。通過操作Value屬性可以改變列的值,通過讀取TypePrecisionNumericScale屬性,可獲知列的數據類型、精度和小數位的個數,通過執行AppendChunkGetChunk方法可以操作列的值。

·??????Error對象

Error對象包含了ADO數據操作時發生錯誤的詳細描述,ADO的任何對象都可以產生一個或者多個數據提供者錯誤,當錯誤發生時,這些錯誤對象被添加到Connection對象的Errors集合里。當另外一個ADO對象產生一個錯誤時,Errors集合里的Error對象被清除,新的Error對象將被添加到Errors集合里。

借助于Errosr對象的集合、方法和屬性,可以通過讀取NumberDescription屬性,獲得ADO錯誤號碼和對錯誤的描述,通過讀取Source屬性得知錯誤發生的源。

·??????Property對象

Property對象代表了一個由提供者定義的ADO對象的動態特征。ADO對象有兩種類型的Property對象:內置的和動態的。內置的Property對象是指那些在ADO里實現的在對象創建時立即可見的屬性,可以通過域作用符直接操作這些屬性。動態的Property對象是指由數據提供者定義的底層的屬性,這些屬性出現在ADO對象的Properties集合里,例如,如果一個Recordset對象支持事務和更新,這些屬性將作為Property對象出現在Recordset對象的Properties集合里。動態屬性必須通過集合進行引用,比如使用下面的語法:

???????MyObject.Properties(0)???

或者

???????MyObject.Properties("Name")

不能刪除任何類型的屬性對象。借助于Property對象的集合、方法和屬性,可以通過讀取Name屬性獲得屬性的名稱,通過讀取Type屬性獲取屬性的數據類型,通過讀取Value屬性獲取屬性的值。

三、ADO編程

?

ADO是以DLL封裝的,要使用ADO,首先得引入其DLL庫,引入ADO類型庫的方法有多種,在此我們就介紹一種----通過預處理指令#import引入。一般情況下,在windows操作系統的Program?Files\Common?Files\System\ado目錄下都有一個msado*.dll文件,根據windows版本不同,該文件可以是msado1.dllmsado15.dllmsado2.dll,對于此文件,版本不一樣,可能導致一些沖突,如:系統自帶的msado*.dll可能與程序編譯所用的版本不一樣,可能會導致一些異常,那么對于這種情況,我個人一般的做法是,在軟件目錄下面帶上msado*.dll文件,這樣就排除了對軟件運行環境的依賴。

?

Ado類型庫引入后,程序在編譯過程中,VC++會讀出msado*.dll中的類型庫信息,自動產生兩個該類型庫的頭文件和實現文件msado15.tlhmsado15.tli(在您的DebugRelease目錄下)。在這兩個文件里定義了ADO的所有對象和方法,以及一些枚舉型的常量等。以下是引入方法:

#import"..\CommFile\Lib\msado15.dll"?named_guids?rename("EOF","adoEOF"),rename("BOF","adoBOF")

//重命名EOFBOF以免與其他命名空間沖突

但要注意不能放在stdAfx.h文件的開頭,而應該放在所有include指令的后面。否則在編譯時會出錯。

初始化COM

????????ADOCOM組件,使用任何COM組件的時候,都要先初始化COM,其實就是在使用COM組件前調用一個API----CoInitialize(),在使用ADO對象之前調用即可,以下為代碼:

HRESULT?hr?=CoInitialize(NULL);

ASSERT(SUCCEEDED(hr));//返回值可判斷初始化COM是否成功,請用SUCCEEDED來判斷

一般情況下,使用完COM之后,調用反初始化COM函數----CoUninitialize()。一般會在數據庫訪問封裝類的析構函數中調用。

三個核心對象

ADO3個核心對象是連接對象(_Connection)、命令對象(_Command)和記錄集對象(_RecordSet)。其中連接對象是任何操作必須的。很多操作3個核心對象都可以完成。要實例化它們并使用它們提供的方法,不得不說到它們是一種智能指針(Smart?Pointer)。在初始化或釋放等操作時,它們是一個對象,用點操作符,其他大部分操作則使用“->”操作符。

?實例化

???????_ConnectionPtr?pConn(__uuidof(Connection));

???????_RecordsetPtr?pRec(__uuidof(Recordset));

???????_CommandPtr?pCmd(__uuidof(Command));

如果上面不加參數,則需加上:

??????????????pConn.CreateInstance("ADODB.Connection");

??????????????pRec.CreateInstance("ADODB.Recordset");

??????????????pCmd.CreateInstance("ADODB.Command");

有些數據庫操作_Connection一個就能完全搞定。如update語句。因為它不需要返回的結果。也有些操作需要返回記錄集,如select語句。這里就至少需要_Connection_Recordset兩種核心對象,也可以用_Command執行之。

?

錯誤捕獲

數據庫操作難免出現錯誤,連接串錯誤,SQL語句錯誤,或返回NULL你卻硬要向表里塞(此錯誤可以在取出后用var.vt!=VT_NULL判斷),所以我們需要把它們放到try…catch段中。ADO在捕獲到錯誤后會拋出_com_error類型異常,我們可以這樣做:

???????try

???????{

??????????????pConn->ConnectionString="Provider=SQLOLEDB.1;Persist?Security?Info=False;User?ID=sa;Password=123;Initial?Catalog=cfdata";

??????????????pConn->Open("","","",adConnectUnspecified);

???…………???//代碼省略

????}

???????catch(_com_error&?e)

???????{

??????????????AfxMessageBox(e.ErrorMessage());

??????????????AfxMessageBox(e.Description());

???????}

????????這里有個疑惑,在捕獲錯誤后,e.ErrorMessage()e.Description()中放著不同信息,有時前者說得清晰,有的后者說的清晰,搞不清楚,索性就都加上吧。最后,可以再加個catch(…),畢竟ADO之外的地方也可能發生錯誤。

這里,我還犯過一個錯誤,被它整了N久。我把_com_error&?e寫成了_com_error*?e后面也對應改成->操作符,而且編譯通過,結果一運行程序就崩潰,而且它不告訴我在哪出錯,因為這時的錯誤是_com_error這時卻對著_com_error*來捕獲當然捕不到。這里&只是一個引用,寫不寫無所謂,*是萬萬不可地。(網上書上很多大師級代碼都是用了*,誤導啊)

?

VARIANTBSTR_variant_t_bstr_t
COM必須設計成跨平臺,需要提供語言無關的數據類型,多數編程語言有自己的字符串表示,需要定義一種通用的字符串類型,可以很容易的匹配到不同編程語言。
C++中,由于COM編程不使用CString,因為它需要一種更普遍的方法來處理字符串和其他數據類型,這就是VARIANT變量數據和BSTR類型的來歷。

Variant?是一種特殊的數據類型,除了定長?String?數據及用戶定義類型外,可以包含任何種類的數據。_variant_t是一個類,它封裝了VARIANT類型。用ADO讀取數據庫中數據的

時候一般用_variant_t
VARIANT的定義和用法可以參見tagVARIANT結構體
----------------------------------------------------------------------------
typedef?struct?tagVARIANT?{
VARTYPE?vt;
unsigned?short?wReserved1;
unsigned?short?wReserved2;
unsigned?short?wReserved3;
union?{
unsigned?char?bVal;?//?VT_UI1.
short?iVal;?//?VT_I2?.
long?lVal;?//?VT_I4?.
……………………………………………………………………………………
void?FAR*?byref;?//?Generic?ByRef.
};
};
-----------------------------------------------------------------------------
下面是使用VARIANT的例子:
VARIANT?theValue;
//Initializes?a?variant——::VariantInit(&theValue);
int?value?=2007;
theValue.vt?=?VT_I4;?//?聲明是long類型(long?lVal;?//?VT_I4)
theValue.lVal?=?value;?//?賦值

如果theValue.vt=VT_ERROR;//沒有初始化
如果theValue.vt=VT_NULL;?//初始化了,但沒有值
如果theValue.vt=VT_EMPTY;?//賦值為空


BSTR(Basic?STRingBasic字符串),用來處理COM中的字符串。BSTR是一個字符串指針,可以存放字符串。它的定義如下:
typedef?OLECHAR?*BSTR;
typedef?WCHAR?OLECHAR;
_bstr_t也是一個類,它封裝了BSTR類型。在操作數據庫時,SQL語言可以用_bstr_t來存放。例如:


CString?sql="select?*?from?table";
m_pCnn->Open(_bstr_t(sql),"","",-1);

或者:
_bstr_t?sql="select?*?from?table";
m_pCnn->Open(sql,"","",-1);

或者:
CString?sql="select?*?from?table";
BSTR?bstrSQL=sql.AllocSysString();
m_pCnn->Open(bstrSQL,"","",-1);


除了_variant_t_bstr_t之外,_com_error也是ado操作中常用到的COM支持類,在comdef.h中定義,使用這些類,可以避免在組件中引起的沖突。

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

總結

以上是生活随笔為你收集整理的ADO学习(一)基础理论的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。