熱點推薦:
您现在的位置: 電腦知識網 >> 編程 >> .NET編程 >> 正文

Visual C++開發數據庫基礎之ADO篇

2013-11-13 10:02:22  來源: .NET編程 

  ADO簡介

  ADO(ActiveX Data Object)是Microsoft數據庫應用程序開發的新接口是建立在OLE DB之上的高層數據庫訪問技術請不必為此擔心即使你對OLE DBCOM不了解也能輕松對付ADO因為它非常簡單易用甚至比你以往所接觸的ODBC APIDAORDO都要容易使用並不失靈活性本文將詳細地介紹在VC下如何使用ADO來進行數據庫應用程序開發並給出示例代碼
 
基本流程

  萬事開頭難任何一種新技術對於初學者來說最重要的還是入門掌握其要點讓我們來看看ADO數據庫開發的基本流程吧!
()初始化COM庫引入ADO庫定義文件
()用Connection對象連接數據庫
()利用建立好的連接通過ConnectionCommand對象執行SQL命令或利用Recordset對象取得結果記錄集進行查詢處理
()使用完畢後關閉連接釋放對象

准備工作:
 為了大家都能測試本文提供的例子我們采用Access數據庫您也可以直接在我們提供的示例代碼中找到這個testmdb
下面我們將詳細介紹上述步驟並給出相關代碼
】COM庫的初始化
我們可以使用AfxOleInit()來初始化COM庫這項工作通常在CWinApp::InitInstance()的重載函數中完成請看如下代碼:

   BOOL CADOTestApp::InitInstance()
  {
  AfxOleInit();
   

  【】用#import指令引入ADO類型庫
 我們在stdafxh中加入如下語句(stdafxh這個文件哪裡可以找到?你可以在FileView中的Header Files裡找到)

   #import c:\program files\common files\system\ado\msadodll no_namespace rename(EOFadoEOF)

  這一語句有何作用呢?其最終作用同我們熟悉的#include類似編譯的時候系統會為我們生成msadotlhadotli兩個C++頭文件來定義ADO庫

幾點說明:
() 您的環境中msadodll不一定在這個目錄下請按實際情況修改
() 在編譯的時候肯能會出現如下警告對此微軟在MSDN中作了說明並建議我們不要理會這個警告
msadotlh() : warning C: unary minus operator applied to unsigned type result still unsigned

】創建Connection對象並連接數據庫
首先我們需要添加一個指向Connection對象的指針:
_ConnectionPtr m_pConnection;
下面的代碼演示了如何創建Connection對象實例及如何連接數據庫並進行異常捕捉

   BOOL CADOTestDlg::OnInitDialog()
  {
  CDialog::OnInitDialog();
  HRESULT hr;
  try
  {
  hr = m_pConnectionCreateInstance(ADODBConnection);///創建Connection對象
  if(SUCCEEDED(hr))
  {
  hr = m_pConnection>Open(Provider=MicrosoftJetOLEDB;Data Source=testmdbadModeUnknown);///連接數據庫
  ///上面一句中連接字串中的Provider是針對ACCESS環境的對於ACCESS需要改為:Provider=MicrosoftJetOLEDB;  }
  }
  catch(_com_error e)///捕捉異常
  {
  CString errormessage;
  errormessageFormat(連接數據庫失敗!\r\n錯誤信息:%seErrorMessage());
  AfxMessageBox(errormessage);///顯示錯誤信息
  } 

  在這段代碼中我們是通過Connection對象的Open方法來進行連接數據庫的下面是該方法的原型
HRESULT Connection::Open ( _bstr_t ConnectionString _bstr_t UserID _bstr_t Password long Options )
ConnectionString為連接字串UserID是用戶名 Password是登陸密碼Options是連接選項用於指定Connection對象對數據的更新許可權
Options可以是如下幾個常量:
adModeUnknown:缺省當前的許可權未設置
adModeRead:只讀
adModeWrite:只寫
adModeReadWrite:可以讀寫
adModeShareDenyRead:阻止其它Connection對象以讀權限打開連接
adModeShareDenyWrite:阻止其它Connection對象以寫權限打開連接
adModeShareExclusive:阻止其它Connection對象打開連接
adModeShareDenyNone:允許其它程序或對象以任何權限建立連接

  我們給出一些常用的連接方式供大家參考:
()通過JET數據庫引擎對ACCESS數據庫的連接


   m_pConnection>Open(Provider=MicrosoftJetOLEDB;Data Source=C:\\testmdbadModeUnknown);

  ()通過DSN數據源對任何支持ODBC的數據庫進行連接:

   m_pConnection>Open(Data Source=adotest;UID=sa;PWD=;adModeUnknown);

  ()不通過DSN對SQL SERVER數據庫進行連接

   m_pConnection>Open(driver={SQL Server};Server=;DATABASE=vckbase;UID=sa;PWD=adModeUnknown); 

  其中Server是SQL服務器的名稱DATABASE是庫的名稱

Connection對象除Open方法外還有許多方法我們先介紹Connection對象中兩個有用的屬性ConnectionTimeOut與State
ConnectionTimeOut用來設置連接的超時時間需要在Open之前調用例如:

   m_pConnection>ConnectionTimeout = ;///設置超時時間為
m_pConnection>Open(Data Source=adotest;adModeUnknown); 

  State屬性指明當前Connection對象的狀態表示關閉表示已經打開我們可以通過讀取這個屬性來作相應的處理例如:

   if(m_pConnection>State)
     m_pConnection>Close(); ///如果已經打開了連接則關閉它 

  【】執行SQL命令並取得結果記錄集
為了取得結果記錄集我們定義一個指向Recordset對象的指針:_RecordsetPtr m_pRecordset;
並為其創建Recordset對象的實例: m_pRecordsetCreateInstance(ADODBRecordset);
SQL命令的執行可以采用多種形式下面我們一進行闡述

()利用Connection對象的Execute方法執行SQL命令
Execute方法的原型如下所示:
_RecordsetPtr Connection::Execute ( _bstr_t CommandText VARIANT * RecordsAffected long Options ) 其中CommandText是命令字串通常是SQL命令參數RecordsAffected是操作完成後所影響的行數 參數Options表示CommandText中內容的類型Options可以取如下值之一
adCmdText:表明CommandText是文本命令
adCmdTable:表明CommandText是一個表名
adCmdProc:表明CommandText是一個存儲過程
adCmdUnknown:未知

Execute執行完後返回一個指向記錄集的指針下面我們給出具體代碼並作說明

     _variant_t RecordsAffected;
  ///執行SQL命令CREATE TABLE創建表格usersusers包含四個字段:整形ID字符串username整形old日期型birthday
  m_pConnection>Execute(CREATE TABLE users(ID INTEGERusername TEXTold INTEGERbirthday DATETIME)&RecordsAffectedadCmdText);
  ///往表格裡面添加記錄
  m_pConnection>Execute(INSERT INTO users(IDusernameoldbirthday) valueS ( Washington//)&RecordsAffectedadCmdText);
  ///將所有記錄old字段的值加一
  m_pConnection>Execute(UPDATE users SET old = old+&RecordsAffectedadCmdText);
  ///執行SQL統計命令得到包含記錄條數的記錄集
  m_pRecordset =  m_pConnection>Execute(SELECT COUNT(*) FROM users&RecordsAffectedadCmdText);
  _variant_t vIndex = (long);
  _variant_t vCount = m_pRecordset>GetCollect(vIndex);///取得第一個字段的值放入vCount變量
  m_pRecordset>Close();///關閉記錄集
  CString message;
  messageFormat(共有%d條記錄vCountlVal);
  AfxMessageBox(message);///顯示當前記錄條數 

  ()利用Command對象來執行SQL命令

     _CommandPtr m_pCommand;
  m_pCommandCreateInstance(ADODBCommand);
  _variant_t vNULL;
  vNULLvt = VT_ERROR;
  vNULLscode = DISP_E_PARAMNOTFOUND;///定義為無參數
  m_pCommand>ActiveConnection = m_pConnection;///非常關鍵的一句將建立的連接賦值給它
  m_pCommand>CommandText = SELECT * FROM users;///命令字串
  m_pRecordset = m_pCommand>Execute(&vNULL&vNULLadCmdText);///執行命令取得記錄集 

  在這段代碼中我們只是用Command對象來執行了SELECT查詢語句Command對象在進行存儲過程的調用中能真正體現它的作用下次我們將詳細介紹

()直接用Recordset對象進行查詢取得記錄集
例如

   m_pRecordset>Open(SELECT * FROM users_variant_t((IDispatch *)m_pConnectiontrue)adOpenStaticadLockOptimisticadCmdText);

  Open方法的原型是這樣的:

   HRESULT Recordset::Open ( const _variant_t & Source const _variant_t & ActiveConnection enum CursorTypeEnum CursorType enum LockTypeEnum LockType long Options ) 

  其中
①Source是數據查詢字符串
②ActiveConnection是已經建立好的連接(我們需要用Connection對象指針來構造一個_variant_t對象)
③CursorType光標類型它可以是以下值之一請看這個枚舉結構:


   enum CursorTypeEnum
{
adOpenUnspecified = ///不作特別指定
adOpenForwardOnly = ///前滾靜態光標這種光標只能向前浏覽記錄集比如用MoveNext向前滾動這種方式可以提高浏覽速度但諸如BookMarkRecordCountAbsolutePositionAbsolutePage都不能使用
adOpenKeyset = ///采用這種光標的記錄集看不到其它用戶的新增刪除操作但對於更新原有記錄的操作對你是可見的
adOpenDynamic = ///動態光標所有數據庫的操作都會立即在各用戶記錄集上反應出來
adOpenStatic = ///靜態光標它為你的記錄集產生一個靜態備份但其它用戶的新增刪除更新操作對你的記錄集來說是不可見的
};

  ④LockType鎖定類型它可以是以下值之一請看如下枚舉結構

   enum LockTypeEnum
{
adLockUnspecified = ///未指定
adLockReadOnly = ///只讀記錄集
adLockPessimistic = 悲觀鎖定方式數據在更新時鎖定其它所有動作這是最安全的鎖定機制
adLockOptimistic = 樂觀鎖定方式只有在你調用Update方法時才鎖定記錄在此之前仍然可以做數據的更新插入刪除等動作
adLockBatchOptimistic = 樂觀分批更新編輯時記錄不會鎖定更改插入及刪除是在批處理模式下完成
};  

  ⑤Options請參考本文中對Connection對象的Execute方法的介紹


】記錄集的遍歷更新
 根據我們剛才通過執行SQL命令建立好的users表它包含四個字段:IDusernameoldbirthday
以下的代碼實現打開記錄集遍歷所有記錄刪除第一條記錄添加三條記錄移動光標到第二條記錄更改其年齡保存到數據庫

   _variant_t vUsernamevBirthdayvIDvOld;
_RecordsetPtr m_pRecordset;
m_pRecordsetCreateInstance(ADODBRecordset);
m_pRecordset>Open(SELECT * FROM users_variant_t((IDispatch*)m_pConnectiontrue)adOpenStaticadLockOptimisticadCmdText);
while(!m_pRecordset>adoEOF)///這裡為什麼是adoEOF而不是EOF呢?還記得rename(EOFadoEOF)這一句嗎?
{
 vID = m_pRecordset>GetCollect(_variant_t((long)));///取得第列的值開始計數你也可以直接給出列的名稱如下一行
 vUsername = m_pRecordset>GetCollect(username);///取得username字段的值
 vOld = m_pRecordset>GetCollect(old);
 vBirthday = m_pRecordset>GetCollect(birthday);
 ///在DEBUG方式下的OUTPUT窗口輸出記錄集中的記錄
 if(vIDvt != VT_NULL && vUsernamevt != VT_NULL && vOldvt != VT_NULL && vBirthdayvt != VT_NULL)
  TRACE(id:%d姓名:%s年齡:%d生日:%s\r\nvIDlVal(LPCTSTR)(_bstr_t)vUsernamevOldlVal(LPCTSTR)(_bstr_t)vBirthday);
 m_pRecordset>MoveNext();///移到下一條記錄
}
m_pRecordset>MoveFirst();///移到首條記錄
m_pRecordset>Delete(adAffectCurrent);///刪除當前記錄
///添加三條新記錄並賦值
for(int i=;i<;i++)
{
 m_pRecordset>AddNew();///添加新記錄
 m_pRecordset>PutCollect(ID_variant_t((long)(i+)));
 m_pRecordset>PutCollect(username_variant_t(葉利欽));
 m_pRecordset>PutCollect(old_variant_t((long)));
 m_pRecordset>PutCollect(birthday_variant_t());
}
m_pRecordset>Move(_variant_t((long)adBookmarkFirst));///從第一條記錄往下移動一條記錄即移動到第二條記錄處
m_pRecordset>PutCollect(_variant_t(old)_variant_t((long)));///修改其年齡
m_pRecordset>Update();///保存到庫中

  【】關閉記錄集與連接
記錄集或連接都可以用Close方法來關閉

         m_pRecordset>Close();///關閉記錄集
      m_pConnection>Close();///關閉連接

 至此我想您已經熟悉了ADO操作數據庫的大致流程也許您已經胸有成竹也許您還有點胡塗不要緊!建議你嘗試寫幾個例子這樣會更好地熟悉ADO最後我給大家寫了一個小例子例子中讀出所有記錄放到列表控件中並可以添加刪除修改記錄

 後記限於篇幅ADO中的許多內容還沒有介紹下次我們將詳細介紹Recordset對象的屬性方法並解決幾個關鍵的技術綁定方式處理記錄集數據存儲過程的調用事務處理圖象在數據庫中的保存與讀取與表格控件的配合使用等


From:http://tw.wingwit.com/Article/program/net/201311/12355.html
    推薦文章
    Copyright © 2005-2013 電腦知識網 Computer Knowledge   All rights reserved.