1.MFC ODBC數(shù)據(jù)庫簡述
開放數(shù)據(jù)互連(Open Database Connectivity,簡稱ODBC)是一種數(shù)據(jù)庫的互操作平臺,通過經(jīng)嚴(yán)格定義的各個級別的ODBC接口和客戶系統(tǒng)的初始裝置,能夠為應(yīng)用程序提供數(shù)據(jù)庫類型透明性和位置透明性,讓應(yīng)用程序的編寫者避免了與數(shù)據(jù)源相聯(lián)的復(fù)雜性。MFC的數(shù)據(jù)庫擴(kuò)展部分封裝了使用ODBC數(shù)據(jù)資源的細(xì)節(jié),應(yīng)用程序可以直接使用MFC中的數(shù)據(jù)庫擴(kuò)展類,來操縱ODBC驅(qū)動程序管理器,訪問數(shù)據(jù)庫。進(jìn)行MFC ODBC數(shù)據(jù)庫開發(fā)時,所需的基礎(chǔ)工具就是MFC ODBC數(shù)據(jù)庫類的使用。利用MFC ODBC開發(fā)就是利用MFC ODBC數(shù)據(jù)庫類來操縱ODBC數(shù)據(jù)源。Visual C++的大多數(shù)ODBC訪問是通過MFC來完成的。Visual C++的MFC類庫定義了幾個數(shù)據(jù)庫類,在利用MFC編程時常常用到,它們是CDatabase(數(shù)據(jù)庫類)、CRecordSet(記錄集類)、和CRecordView(可視記錄集類)。對于MFC ODBC數(shù)據(jù)庫類來說,CDatabase類對象表示一個同數(shù)據(jù)源的連接,通過它可以對數(shù)據(jù)源進(jìn)行操作。而CRecordSet對象代表從數(shù)據(jù)源中選擇的一組記錄的集合,也就是通常所說的記錄集對象。CRecordSet對象通常用于兩種形式:動態(tài)集(dynasets)和快照集(snapshots)。動態(tài)集能與其他用戶所做的更改保持同步,快照集則是數(shù)據(jù)的一個靜態(tài)視圖。每一種形式在記錄被打開時都提供一組記錄,區(qū)別在于,當(dāng)用戶在一個動態(tài)集里滾動到一條記錄時,有其他用戶或是應(yīng)用程序中的其他記錄集所做的更改就會相應(yīng)地顯示出來。CRecordView類對象能以控制的形式顯示數(shù)據(jù)庫記錄。這個視圖是直接連接到一個CRecordSet對象的表視圖。
2.一個應(yīng)用實例
本實例是某項目中的一部分,目的是實現(xiàn)MFC ODBC數(shù)據(jù)庫與Access數(shù)據(jù)表格之間的相互操作。包括用Visual C++中的MFC ODBC技術(shù)實現(xiàn)對Access數(shù)據(jù)表格的內(nèi)容的顯示、添加、修改和刪除的功能。
2.1 ODBC數(shù)據(jù)源的創(chuàng)建
筆者使用的操作系統(tǒng)為Windows XP,工具是Visual C++6.0。此例中建立的Access表格取名為“plc”。
在“控制面板”中雙擊“管理工具”圖標(biāo),然后在新出現(xiàn)的窗口中雙擊“數(shù)據(jù)源(ODBC)”,在彈出的對話框中選中“用戶DSN”中的“dBASE Files”,單擊“添加”按鈕,從彈出的對話框中選中“Microsoft Access Driver(*.mdb)”。單擊“完成”后,將彈出一個新的對話框,在數(shù)據(jù)源名及說明后的編輯框中填入表格名“plc”。
在命名數(shù)據(jù)源之后,需要把它連接到一個數(shù)據(jù)庫。單擊“選擇”,如圖1所示,得到存儲在數(shù)據(jù)目錄中plc.mdb的拷貝文件,選中之,單擊“確定”關(guān)閉此對話框。然后單擊“確定”,完成數(shù)據(jù)源的創(chuàng)建。
2.2 使用AppWizard創(chuàng)建一個數(shù)據(jù)庫應(yīng)用程序
筆者開始從AppWizard開始創(chuàng)建一個新的MFC AppWizard(exe)項目。命名為Jh,然后遵從以下步驟:
1)在MFC AppWizard第一步對話框中,選擇“單個文檔”。
2)在MFC AppWizard第二步對話框中,選擇“查看數(shù)據(jù)庫不使用文件支持”,再單擊“Data Source”。
3)在RecordSet Type組框中,選擇Dynaset。在Data Source組框中,單擊ODBC單選按鈕,然后從下拉列表中選擇plc,如圖2所示,單擊ok,在彈出的新的對話框中選中message,即為本項目所要操作的表。
以后幾步接收缺省值,單擊“完成”即可。至此,已創(chuàng)建一個應(yīng)用程序,并且在程序中自行生成一個數(shù)據(jù)源和數(shù)據(jù)源中的一個表的相關(guān)程序,其程序清單如下:
class CJhSet : public Crecordset//基于CRecordset的CjhSet新類
{
public:
CJhSet(CDatabase* pDatabase = NULL);
DECLARE_DYNAMIC(CJhSet)
// Field/Param Data
//{{AFX_FIELD(CJhSet, CRecordset)
//對應(yīng)表中一些被綁定字段的變量
CString m_baudrate;
CString m_type;
CString m_unit;
CString m_number;
CString m_address;
CString m_istart;
CString m_iend;
CString m_ostart;
CString m_oend;
//}}AFX_FIELD
// Overrides
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CJhSet)
public:
virtual CString GetDefaultConnect(); // 返回被連接的數(shù)據(jù)源名稱
virtual CString GetDefaultSQL(); // 返回數(shù)據(jù)源中所選表名稱
virtual void DoFieldExchange(CFieldExchange* pFX); // RFX support
//}}AFX_VIRTUAL
// Implementation
#ifdef _DEBUG
virtual void AssertValid() const;
virtual void Dump(CDumpContext& dc) const;
#endif};
2.3 實現(xiàn)程序的顯示記錄的功能
一旦AppWizard完成編寫這些文件,它將啟動對話框編輯器,這樣就可以設(shè)計自己的表單了。CRecordView應(yīng)用程序圍繞著充當(dāng)應(yīng)用程序主窗口的對話框而創(chuàng)建。筆者也將使用像表單一樣的對話框來顯示存儲在plc數(shù)據(jù)庫記錄域中的值。如圖3所示來放置靜態(tài)文本框與編輯文本框。
CJHSet類的成員變量如圖4所示。所有的變量均為CString對象。由AppWizard創(chuàng)建的每個變量的類型一般與相應(yīng)數(shù)據(jù)庫域的類型相似。除了創(chuàng)建成員變量,AppWizard還編寫了一組數(shù)據(jù)交換函數(shù)——類似于對話框的DDX函數(shù)——來在用來顯示信息的控件與定義于CRecordSet類中的數(shù)據(jù)庫域之間交換信息。
為了實現(xiàn)數(shù)據(jù)傳輸,就要把每個控件與代表數(shù)據(jù)庫域的CJHSet變量聯(lián)系起來。筆者通過使用CJHView來成員變量m_pSet來指向應(yīng)用程序的CJHSet對象。選擇每個資源ID(筆者這里未修改編輯框的默認(rèn)ID),并單擊Add Variable,從下拉表中直接選擇相應(yīng)的成員變量名。全部設(shè)置好之后單擊OK,至此,運(yùn)行程序,就可以實現(xiàn)簡單的與數(shù)據(jù)庫之間的數(shù)據(jù)顯示功能。
2.4 實現(xiàn)程序的添加、修改和刪除記錄的功能。
在實現(xiàn)上述功能之前,需要按“插入->資源->DIALOG->新建”建立一個新的對話框(與圖1所示對話框類似),以建立添加、修改的對象。并為此對話框建立一個基于CDialog基礎(chǔ)類的新的類CAddDlg。其ID為IDD_DIALOG1。
然后在JhView.cpp中加“#include "AddDlg.h"”,并為“添加記錄(IDC_ADD)”鍵編寫程序代碼如下。其中已經(jīng)作了詳細(xì)的注解。
void CJhView::OnAdd()
{
//建立一個新的添加對話框
CAddDlg dlg;
if(dlg.DoModal()==IDOK)
{
//增加一條新的記錄
m_pSet->AddNew();
//把對話框中的記錄傳遞到記錄集中
m_pSet->m_baudrate=dlg.m_br;
m_pSet->m_type=dlg.m_ty;
m_pSet->m_unit=dlg.m_un;
m_pSet->m_number=dlg.m_nu;
m_pSet->m_address=dlg.m_add;
m_pSet->m_istart=dlg.m_is;
m_pSet->m_iend=dlg.m_ie;
m_pSet->m_ostart=dlg.m_os;
m_pSet->m_oend=dlg.m_oe;
m_pSet->Update(); //把新的記錄存在數(shù)據(jù)源里
m_pSet->MoveLast(); //指定當(dāng)前記錄為最后一條記錄
UpdateData(false); //清空已輸入內(nèi)容
}
}
添加記錄部分,應(yīng)該先讀出當(dāng)前的記錄,使其顯示在添加/修改對話框中,即:
dlg.m_br=m_pSet->m_baudrate;
dlg.m_ty=m_pSet->m_type;
dlg.m_un=m_pSet->m_unit;
dlg.m_nu=m_pSet->m_number;
dlg.m_add=m_pSet->m_address;
dlg.m_is=m_pSet->m_istart;
dlg.m_ie=m_pSet->m_iend;
dlg.m_os=m_pSet->m_ostart;
dlg.m_oe=m_pSet->m_oend;
余下的與添加記錄代碼相同,除了不要定位“m_pSet->MoveLast();”而已。
刪除記錄只是需要使用Delete()成員函數(shù)刪除當(dāng)前記錄之后移到下一個記錄即可。程序清單如下:
void CJhView::OnDel()
{
try//試著刪除一條記錄
{
m_pSet->Delete();
}
catch(CDBException*error)
{
AfxMessageBox(error->m_strError);
error->Delete();
m_pSet->MoveFirst();
UpdateData(FALSE);
return;
}
//移到下一個記錄
m_pSet->MoveNext();
//測試是否為文件末尾,是,則使用MoveLast(),而不是使用MoveNext()
if(m_pSet->IsEOF())
m_pSet->MoveLast();
UpdateData(FALSE);
}
對多個記錄集的操作與對單個記錄集的操作類似,只是增加了CRecordSet類的派生類。
2.5 結(jié)束語
MFC ODBC讓開發(fā)人員僅僅使用很少的代碼就可以完成復(fù)雜的數(shù)據(jù)庫訪問,并可以對數(shù)據(jù)庫中的內(nèi)容方便的實現(xiàn)添加、修改、刪除等操作,從而極大地減少了軟件開發(fā)的工作量,縮短了開發(fā)周期,提高了效率。而且MFC ODBC簡單易學(xué),能實現(xiàn)大部分ODBC API函數(shù)的功能,所以了解和掌握MFC ODBC技術(shù),將會給大型數(shù)據(jù)庫應(yīng)用軟件帶來清晰、快捷、方便等功能。本文中的實例已經(jīng)在Visual C++6.0環(huán)境下調(diào)試通過。
參考文獻(xiàn):
【1】 李閩溟等著,Visual C++6.0數(shù)據(jù)庫系統(tǒng)開發(fā)實例導(dǎo)航,人民郵電出版社,2002.10
【2】 (美)Stephen D.Gilbert等著,跟我學(xué)Visual C++6.0,機(jī)械工業(yè)出版社,1999.4