MFC連接Access講解(3合1)

方法一:
1.首先,要用#import語句來引用支持ADO的組件類型庫(*.tlb),其中類型庫可以作爲可執行程序(DLL、EXE等)的一部分被定位在其自身程序中的附屬資源裏,如:被定位在msado15.dll的附屬資源中,只需要直接用 #import引用它既可。可以直接在Stdafx.h文件中加入下面語句來實現:
#import "c:/program files/common files/system/ado/msado15.dll" no_namespace rename("EOF", "adoEOF") 【注意,在MFC中路徑要用"/"或者"//"】
其中路徑名可以根據自己系統安裝的ADO支持文件的路徑來自行設定。當編譯器遇到#import語句時,它會爲引用組件類型庫中的接口生成包裝類,#import語句實際上相當於執行了API涵數LoadTypeLib()。#import語句會在工程可執行程序輸出目錄中產生兩個文件,分別爲*.tlh(類型庫頭文件)及*.tli(類型庫實現文件),它們分別爲每一個接口產生智能指針,併爲各種接口方法、枚舉類型,CLSID等進行聲明,創建一系列包裝方法。語句no_namespace說明ADO對象不使用命名空間,rename ("EOF", "adoEOF")說明將ADO中結束標誌EOF改爲adoEOF,以避免和其它庫中命名相沖突。
    2.其次,在程序初始過程中需要初始化組件,一般可以用CoInitialize(NULL);來實現,這種方法在結束時要關閉初始化的COM,可以用下面語句CoUnInitialize();來實現。在MFC中還可以採用另一種方法來實現初始化COM,這種方法只需要一條語句便可以自動爲我們實現初始化COM和結束時關閉COM的操作,語句如下所示: AfxOleInit();

    3.接着,就可以直接使用ADO的操作了。我們經常使用的只是前面用#import語句引用類型庫時,生成的包裝類.tlh中聲明的智能指針中的三個,它們分別是_ConnectionPtr、_RecordsetPtr和_CommandPtr。下面分別對它們的使用方法進行介紹:
_ConnectionPtr接口返回一個記錄集或一個空指針。通常使用它來創建一個數據連接或執行一條不返回任何結果的SQL語句,如一個存儲過程。使用 _ConnectionPtr接口返回一個記錄集不是一個好的使用方法。對於要返回記錄的操作通常用_RecordserPtr來實現。而用 _ConnectionPtr操作時要想得到記錄條數得遍歷所有記錄,而用_RecordserPtr時不需要。
    _CommandPtr接口返回一個記錄集。它提供了一種簡單的方法來執行返回記錄集的存儲過程和SQL語句。在使用_CommandPtr接口時,你可以利用全局 _ConnectionPtr接口,也可以在_CommandPtr接口裏直接使用連接串。如果你只執行一次或幾次數據訪問操作,後者是比較好的選擇。但如果你要頻繁訪問數據庫,並要返回很多記錄集,那麼,你應該使用全局_ConnectionPtr接口創建一個數據連接,然後使用_CommandPtr 接口執行存儲過程和SQL語句。
    _RecordsetPtr是一個記錄集對象。與以上兩種對象相比,它對記錄集提供了更多的控制功能,如記錄鎖定,遊標控制等。同_CommandPtr接口一樣,它不一定要使用一個已經創建的數據連接,可以用一個連接串代替連接指針賦給 _RecordsetPtr的connection成員變量,讓它自己創建數據連接。如果你要使用多個記錄集,最好的方法是同Command對象一樣使用已經創建了數據連接的全局_ConnectionPtr接口,然後使用_RecordsetPtr執行存儲過程和SQL語句。

    代碼:

1.建立一個MFC對話框工程

2.在stdafx.h導入#import "C://Program Files//Common Files//System//ado//msado15.dll" no_namespace rename("EOF","adoEOF")rename("BOF","adoBOF")
3.新建一個Generic Class,取名AdoAccess。

在public:下添加成員函數     

     _ConnectionPtr   m_pConnection; // 數據庫
      _RecordsetPtr    m_pRecordset; // 命令
      _CommandPtr      m_pCommand; // 記錄
      void OnInitADOConn();
      void ExitConnect();
然後寫OnInitADOConn()和ExitConnect()函數
void AdoAccess::OnInitADOConn()
{
::CoInitialize(NULL);
try
{
        m_pConnection.CreateInstance("ADODB.Connection");

或者 m_pConnection.CreateInstance(__uuidof(Connection));
   _bstr_t strConnect="Provider=Microsoft.Jet.OLEDB.4.0;Data Source=Home.mdb";//Home.mdb放在工程目錄下   m_pConnection->Open(strConnect,"","",adModeUnknown);

    AfxMessageBox("連接成功");
}
catch(_com_error e)
{
   AfxMessageBox("連接失敗");
}
}
//這裏是連接master數據庫,無密碼。
void AdoAccess::ExitConnect()
{
     if(m_pRecordset!=NULL)
    m_pRecordset->Close();
   m_pConnection->Close();
   ::CoUninitialize();
}
4.可以開始用了:
首先,把我們類的頭文件包含在主程序#include "AdoAccess.h"
申明一個全局變量:AdoAccess myAccess;//對象聲明
連接的代碼可以做一個按鈕eg:void CTestDBDlg::OnButton1()
{
// TODO: Add your control notification handler code here
myAccess.OnInitADOConn();//連接到數據庫
}
或者在插入在OnInitDialog()函數裏就行了。

查詢數據:

m_pRecordset.CreateInstance("ADODB.Recordset");
   m_pRecordset->Open("SELECT * FROM Type",m_pConnection.GetInterfacePtr(),
    adOpenDynamic,
    adLockOptimistic,
    adCmdText);
   while(!m_pRecordset->adoEOF)
   {
    _variant_t var;
    CString strValue ;
   var = m_pRecordset->GetCollect("Type");
    if(var.vt != VT_NULL)
    strValue = (LPCSTR)_bstr_t(var);
   
    AfxMessageBox(strValue);
    m_pRecordset->MoveNext();
   }

方法二:


 

首先在VC++中建立一個基於對話框的工程(在這裏取名爲sjtest)

1、 在StdAfx.h頭文件中導入msado15.dll文件。(代碼如下)

#import "C:/Program Files/Common Files/System/ado/msado15.dll" no_namespace /

rename("EOF","adoEOF")rename("BOF","adoBOF")

2、 在主窗口類聲明兩個變量。(在CsjtestDlg.h中)

代碼:

_ConnectionPtr m_pConnection;

       _RecordsetPtr m_pRecordset;

關於_ConnectionPtr 和_RecordsetPtr 兩個智能指針具體作用網上很多,我不詳述。想了解的請讀者自己查詢,本文旨在爲大家建立起數據庫連接並且顯示出來!

3、 在對話框中添加一個ListControl控件,並且將其屬性中的Style設置如圖

將View設置成Report,Single selection,auto arrange no label wrap勾上!

 

4、 在CLASS WIZARD裏面添加一個和LISTCONTROL想關聯的變量m_Grid。

 

5、在CSjtestApp應用程序類中的初始化函數InitInstance()中初始化COM環境

在上面添加:       ::CoInitialize(NULL);

並在return之前釋放:添加代碼如下:    ::CoUninitialize();

5、 建立ADO連接數據庫函數

在主窗口類(CSjktestDlg)庫中添加函數OnInitADOConn()如圖:

 

並在該函數添加如下代碼:

       try

       {

              //創建連接對象實例

              m_pConnection.CreateInstance("ADODB.Connection");

              //設置連接字符串

              CString strConnect="DRIVER={Microsoft Access Driver (*.mdb)};/

                     uid=;pwd=;DBQ=shujuku.mdb;";

              //使用Open方法連接數據庫

              m_pConnection->Open((_bstr_t)strConnect,"","",adModeUnknown);

       }

       catch(_com_error e)

       {

              AfxMessageBox("連接數據失敗,請檢查數據庫路徑是否正確!");

       }

在這裏我的數據名字爲shujuku.mdb,當然CString strConnect="DRIVER={Microsoft Access Driver (*.mdb)};    uid=;pwd=;DBQ=shujuku.mdb;";也可以使用如下字符串連接

       CString strConnect="Provider=Microsoft.Jet.OLEDB.4.0;Data Source=shujuku.mdb;Persist Security Info=False";代替

6、 按照第五步那樣建立關閉記錄集和連接函數ExitConnect()並添加代碼:

       //關閉記錄集和連接

    if(m_pRecordset!=NULL)

              m_pRecordset->Close();

       m_pConnection->Close();

7、 接着在初始化對話框中調用OnInitADOConn函數,已經獲取數據庫表中數據並顯示在列表控件中。代碼如下:

       m_Grid.SetExtendedStyle(LVS_EX_FLATSB

              |LVS_EX_FULLROWSELECT

              |LVS_EX_HEADERDRAGDROP

              |LVS_EX_ONECLICKACTIVATE

              |LVS_EX_GRIDLINES);

       m_Grid.InsertColumn(0,"員工編號",LVCFMT_LEFT,80,0);

       m_Grid.InsertColumn(1,"員工姓名",LVCFMT_LEFT,80,1);

       m_Grid.InsertColumn(2,"所屬部門",LVCFMT_LEFT,80,2);

       m_Grid.InsertColumn(3,"基本工資",LVCFMT_LEFT,80,3);

       //連接數據庫

       OnInitADOConn();

       //設置查詢字符串

       _bstr_t bstrSQL = "select * from employees order by 員工編號 desc";

       //創建記錄集指針對象實例

       m_pRecordset.CreateInstance(__uuidof(Recordset));//該句也可以使用

//     m_pRecordset.CreateInstance(“ADODB.Recordset”);代替

       //打開記錄集

       m_pRecordset->Open(bstrSQL,m_pConnection.GetInterfacePtr(),adOpenDynamic,

              adLockOptimistic,adCmdText);

       while(!m_pRecordset->adoEOF)

       {

              m_Grid.InsertItem(0,"");

              m_Grid.SetItemText(0,0,(char*)(_bstr_t)m_pRecordset->GetCollect("員工編號"));

              m_Grid.SetItemText(0,1,(char*)(_bstr_t)m_pRecordset->GetCollect("員工姓名"));

              m_Grid.SetItemText(0,2,(char*)(_bstr_t)m_pRecordset->GetCollect("所屬部門"));

              m_Grid.SetItemText(0,3,(char*)(_bstr_t)m_pRecordset->GetCollect("基本工資"));

              //將記錄集指針移動到下一條記錄

              m_pRecordset->MoveNext();

       }

       //斷開數據庫連接

       ExitConnect();

  

方法三:

我在《VC知識庫在線雜誌》第十四期和第十五期上曾發表了兩篇文章——“直接通過ODBC讀、寫Excel表格文件”和“直接通過DAO讀、寫Access文件”,先後給大家介紹了ODBC和DAO兩種數據庫訪問技術的基本使用方法,這次要給大家介紹的是ADO數據庫訪問技術的使用方法。ADO(Active Data Object,活動數據對象)實際上是一種基於COM(組件對象模型)的自動化接口(IDispatch)技術,並以OLE DB(對象連接和鑲入的數據庫)爲基礎,經過OLE DB精心包裝後的數據庫訪問技術,利用它可以快速的創建數據庫應用程序。 ADO提供了一組非常簡單,將一般通用的數據訪問細節進行封裝的對象。由於ODBC數據源也提供了一般的OLE DB Privider,所以ADO不僅可以應用自身的OLE DB Privider,而且還可以應用所有的ODBC驅動程序。關於OLE DB和ADO的其它詳細情況,讀者可以自行查閱相關書籍或MSDN,這裏就不一一說明了。讓我們直接步入主題:如何掌握ADO這種數據庫訪問技術。ADO的操作方法和前面講過的DAO的操作在很多方面存在相似之處,在這裏,筆者爲了更有效的說明它的使用方法,用VC6.0做了一個示例程序——AdoRWAccess,這個示例程序可以直接通過ADO來操作Access數據庫,示例程序的運行效果如下圖所示:



在示例程序中我們仍採用原庫結構,數據庫名Demo.mdb,庫內表名DemoTable,表內字段名爲Name(姓名)和Age(年齡)的兩個字段,來構造示例程序操作所需的Access數據庫,這也和上兩篇文章的示例源碼中的庫結構相兼容。
下面讓我們看看ADO數據庫訪問技術使用的基本步驟及方法:
    首先,要用#import語句來引用支持ADO的組件類型庫(*.tlb),其中類型庫可以作爲可執行程序(DLL、EXE等)的一部分被定位在其自身程序中的附屬資源裏,如:被定位在msado15.dll的附屬資源中,只需要直接用#import引用它既可。可以直接在Stdafx.h文件中加入下面語句來實現:

#import "c:/program files/common files/system/ado/msado15.dll" /
 no_namespace /
 rename ("EOF", "adoEOF")
其中路徑名可以根據自己系統安裝的ADO支持文件的路徑來自行設定。當編譯器遇到#import語句時,它會爲引用組件類型庫中的接口生成包裝類,#import語句實際上相當於執行了API涵數LoadTypeLib()。#import語句會在工程可執行程序輸出目錄中產生兩個文件,分別爲*.tlh(類型庫頭文件)及*.tli(類型庫實現文件),它們分別爲每一個接口產生智能指針,併爲各種接口方法、枚舉類型,CLSID等進行聲明,創建一系列包裝方法。語句no_namespace說明ADO對象不使用命名空間,rename ("EOF", "adoEOF")說明將ADO中結束標誌EOF改爲adoEOF,以避免和其它庫中命名相沖突。
    其次,在程序初始過程中需要初始化組件,一般可以用CoInitialize(NULL);來實現,這種方法在結束時要關閉初始化的COM,可以用下面語句CoUnInitialize();來實現。在MFC中還可以採用另一種方法來實現初始化COM,這種方法只需要一條語句便可以自動爲我們實現初始化COM和結束時關閉COM的操作,語句如下所示: AfxOleInit();
    接着,就可以直接使用ADO的操作了。我們經常使用的只是前面用#import語句引用類型庫時,生成的包裝類.tlh中聲明的智能指針中的三個,它們分別是_ConnectionPtr、_RecordsetPtr和_CommandPtr。下面分別對它們的使用方法進行介紹:
1、_ConnectionPtr智能指針,通常用於打開、關閉一個庫連接或用它的Execute方法來執行一個不返回結果的命令語句(用法和_CommandPtr中的Execute方法類似)。
——打開一個庫連接。先創建一個實例指針,再用Open打開一個庫連接,它將返回一個IUnknown的自動化接口指針。代碼如下所示:
_ConnectionPtr m_pConnection;
// 初始化COM,創建ADO連接等操作
AfxOleInit();
m_pConnection.CreateInstance(__uuidof(Connection));

// 在ADO操作中建議語句中要常用try...catch()來捕獲錯誤信息,
// 因爲它有時會經常出現一些意想不到的錯誤。jingzhou xu
try                 
{ 
 // 打開本地Access庫Demo.mdb
 m_pConnection->Open("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=Demo.mdb","","",adModeUnknown);
}
catch(_com_error e)
{
 AfxMessageBox("數據庫連接失敗,確認數據庫Demo.mdb是否在當前路徑下!");
 return FALSE;
}
——關閉一個庫連接。如果連接狀態有效,則用Close方法關閉它並賦於它空值。代碼如下所示:
if(m_pConnection->State)
        m_pConnection->Close();
m_pConnection= NULL;
2、_RecordsetPtr智能指針,可以用來打開庫內數據表,並可以對錶內的記錄、字段等進行各種操作。
——打開數據表。打開庫內表名爲DemoTable的數據表,代碼如下:
_RecordsetPtr m_pRecordset;
m_pRecordset.CreateInstance(__uuidof(Recordset));

// 在ADO操作中建議語句中要常用try...catch()來捕獲錯誤信息,
// 因爲它有時會經常出現一些意想不到的錯誤。jingzhou xu
try
{
 m_pRecordset->Open("SELECT * FROM DemoTable",                // 查詢DemoTable表中所有字段
      theApp.m_pConnection.GetInterfacePtr(),  // 獲取庫接庫的IDispatch指針
      adOpenDynamic,
      adLockOptimistic,
      adCmdText);
}
catch(_com_error *e)
{
 AfxMessageBox(e->ErrorMessage());
}
——讀取表內數據。將表內數據全部讀出並顯示在列表框內,m_AccessList爲列表框的成員變量名。如果沒有遇到表結束標誌adoEOF,則用GetCollect(字段名)或m_pRecordset->Fields->GetItem(字段名)->Value方法,來獲取當前記錄指針所指的字段值,然後再用MoveNext()方法移動到下一條記錄位置。代碼如下所示:
_variant_t var;
CString strName,strAge;
 try
 {
  if(!m_pRecordset->BOF)
   m_pRecordset->MoveFirst();
  else
  {
   AfxMessageBox("表內數據爲空");
   return;
  }

  // 讀入庫中各字段並加入列表框中
  while(!m_pRecordset->adoEOF)
  {
   var = m_pRecordset->GetCollect("Name");
   if(var.vt != VT_NULL)
    strName = (LPCSTR)_bstr_t(var);
   var = m_pRecordset->GetCollect("Age");
   if(var.vt != VT_NULL)
    strAge = (LPCSTR)_bstr_t(var);

   m_AccessList.AddString( strName + " --> "+strAge );

   m_pRecordset->MoveNext();
  }

  // 默認列表指向第一項,同時移動記錄指針並顯示
  m_AccessList.SetCurSel(0);
 }
 catch(_com_error *e)
 {
  AfxMessageBox(e->ErrorMessage());
 }
——插入記錄。可以先用AddNew()方法新增一個空記錄,再用PutCollect(字段名,值)輸入每個字段的值,最後再Update()更新到庫中數據既可。其中變量m_Name和m_Age分別爲姓名及年齡編輯框的成員變量名。代碼所下所示:
try
 {
  // 寫入各字段值
  m_pRecordset->AddNew();
  m_pRecordset->PutCollect("Name", _variant_t(m_Name));
  m_pRecordset->PutCollect("Age", atol(m_Age));
  m_pRecordset->Update();

  AfxMessageBox("插入成功!");
 }
 catch(_com_error *e)
 {
  AfxMessageBox(e->ErrorMessage());
 }
——移動記錄指針。移動記錄指針可以通過MoveFirst()方法移動到第一條記錄、MoveLast()方法移動到最後一條記錄、MovePrevious()方法移動到當前記錄的前一條記錄、MoveNext()方法移動到當前記錄的下一條記錄。但我們有時經常需要隨意移動記錄指針到任意記錄位置時,可以使用Move(記錄號)方法來實現,注意: Move()方法是相對於當前記錄來移動指針位置的,正值向後移動、負值向前移動,如:Move(3),當前記錄是3時,它將從記錄3開始往後再移動3條記錄位置。代碼如下所示:
try
 {
  int curSel = m_AccessList.GetCurSel(); 
  // 先將指針移向第一條記錄,然後就可以相對第一條記錄來隨意移動記錄指針
  m_pRecordset->MoveFirst();
  m_pRecordset->Move(long(curSel));
  
 }
 catch(_com_error *e)
 {
  AfxMessageBox(e->ErrorMessage());
 }
——修改記錄中字段值。可以將記錄指針移動到要修改記錄的位置處,直接用PutCollect(字段名,值)將新值寫入並Update()更新數據庫既可。可以用上面方法移動記錄指針,修改字段值代碼如下所示:
try
 {
  // 假設對第二條記錄進行修改
  m_pRecordset->MoveFirst();
  m_pRecordset->Move(1);        // 從0開始
  m_pRecordset->PutCollect("Name", _variant_t(m_Name));
  m_pRecordset->PutCollect("Age", atol(m_Age));
  m_pRecordset->Update();
 }
 catch(_com_error *e)
 {
  AfxMessageBox(e->ErrorMessage());
 }
——刪除記錄。刪除記錄和上面修改記錄的操作類似,先將記錄指針移動到要修改記錄的位置,直接用Delete()方法刪除它並用Update()來更新數據庫既可。代碼如下所示:
try
 {
  // 假設刪除第二條記錄
  m_pRecordset->MoveFirst();
  m_pRecordset->Move(1);        // 從0開始
  m_pRecordset->Delete(adAffectCurrent);  // 參數adAffectCurrent爲刪除當前記錄
  m_pRecordset->Update();
 }
 catch(_com_error *e)
 {
  AfxMessageBox(e->ErrorMessage());
 }
——關閉記錄集。直接用Close方法關閉記錄集並賦於其空值。代碼如下所示:
m_pRecordset->Close();
 m_pRecordset = NULL;
3、CommandPtr智能指針,可以使用_ConnectionPtr或_RecordsetPtr來執行任務,定義輸出參數,執行存儲過程或SQL語句。
——執行SQL語句。先創建一個_CommandPtr實例指針,再將庫連接和SQL語句做爲參數,執行Execute()方法既可。代碼如下所示:
_CommandPtr  m_pCommand;
m_pCommand.CreateInstance(__uuidof(Command));
m_pCommand->ActiveConnection = m_pConnection;  // 將庫連接賦於它
m_pCommand->CommandText = "SELECT * FROM DemoTable";  // SQL語句
m_pRecordset = m_pCommand->Execute(NULL, NULL,adCmdText); // 執行SQL語句,返回記錄集
——執行存儲過程。執行存儲過程的操作和上面執行SQL語句類似,不同點僅是CommandText參數中不再是SQL語句,而是存儲過程的名字,如Demo。另一個不同點就是在Execute()中參數由adCmdText(執行SQL語句),改爲adCmdStoredProc來執行存儲過程。如果存儲過程中存在輸入、輸出參數的話,需要使用到另一個智能指針_ParameterPtr來逐次設置要輸入、輸出的參數信息,並將其賦於_CommandPtr中Parameters參數來傳遞信息,有興趣的讀者可以自行查找相關書籍或MSDN。執行存儲過程的代碼如下所示:
_CommandPtr  m_pCommand;
m_pCommand.CreateInstance(__uuidof(Command));
  m_pCommand->ActiveConnection = m_pConnection;  // 將庫連接賦於它
m_pCommand->CommandText = "Demo";  
  m_pCommand->Execute(NULL,NULL, adCmdStoredProc)
 
來源:http://www.vckbase.com/document/viewdoc/?id=496
作者:徐景周
發佈了26 篇原創文章 · 獲贊 0 · 訪問量 4萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章