08 DAO
10.8.1 什么是DAO
DAO(Database Access Object)使用Microsoft Jet數(shù)據(jù)庫(kù)引擎來(lái)訪問(wèn)數(shù)據(jù)庫(kù)。Microsoft Jet為象Access和Visual Basic這樣的產(chǎn)品提供了數(shù)據(jù)引擎。
與ODBC一樣,DAO提供了一組API供編程使用。MFC也提供了一組DAO類(lèi),封裝了底層的API,從而大大簡(jiǎn)化了程序的開(kāi)發(fā)。利用MFC的DAO類(lèi),用戶可以編寫(xiě)?yīng)毩⒂?/font>DBMS的應(yīng)用程序。
DAO是從Visual C++4.0版開(kāi)始引入的。一般地講,DAO類(lèi)提供了比ODBC類(lèi)更廣泛的支持。一方面,只要有ODBC驅(qū)動(dòng)程序,使用Microsoft Jet的DAO就可以訪問(wèn)ODBC數(shù)據(jù)源。另一方面,由于DAO是基于Microsoft Jet引擎的,因而在訪問(wèn)Access數(shù)據(jù)庫(kù)(即*.MDB文件)時(shí)具有很好的性能。
10.8.2 DAO和ODBC的相似之處
DAO類(lèi)與ODBC類(lèi)相比具有很多相似之處,這主要有下面幾點(diǎn):
-
-
二者都支持對(duì)各種ODBC數(shù)據(jù)源的訪問(wèn)。雖然二者使用的數(shù)據(jù)引擎不同,但都可以滿足用戶編寫(xiě)?yīng)毩⒂?font face="Times New Roman" size="3">DBMS
-
-
DAO提供了與ODBC功能相似的MFC類(lèi)。例如,DAO的CDaoDatabase類(lèi)對(duì)應(yīng)ODBC的CDatabase類(lèi),CDaoRecordset對(duì)應(yīng)CRecordset,CDaoRecordView對(duì)應(yīng)CRecordView,CDaoException對(duì)應(yīng)CDBException。這些對(duì)應(yīng)的類(lèi)功能相似,它們的大部分成員函數(shù)都是相同的。
-
AppWizard和ClassWizard對(duì)使用DAO和ODBC對(duì)象的應(yīng)用程序提供了類(lèi)似的支持。
由于DAO和ODBC類(lèi)的許多方面都比較相似,因此只要用戶掌握了ODBC,就很容易學(xué)會(huì)使用DAO。實(shí)際上,用戶可以很輕松地把數(shù)據(jù)庫(kù)應(yīng)用程序從ODBC移植到DAO。
Visual C++隨盤(pán)提供了一個(gè)名為DaoEnrol的例子,該例實(shí)際上是Enroll的一個(gè)DAO版本。讀者可以打開(kāi)DaoEnrol工程看一看,它的源代碼與Enroll的極為相似。讀者可以按照建立Enroll的步驟來(lái)建立DaoEnrol,其中只有若干個(gè)地方有差別,這主要有以下幾點(diǎn):
選取的數(shù)據(jù)源不同。在用AppWizard創(chuàng)建DaoEnrol時(shí),以及在用ClassWizard創(chuàng)建CDaoRecordset類(lèi)的派生類(lèi)時(shí),在Database Options對(duì)話框中應(yīng)該選擇DAO而不是ODBC。而且DAO的數(shù)據(jù)源是通過(guò)選擇一個(gè).MDB文件來(lái)指定的,即點(diǎn)擊“...”按鈕后在文件對(duì)話框中選擇要訪問(wèn)的.MDB文件。
記錄集的缺省類(lèi)型不同。ODBC記錄集的缺省類(lèi)型是快照(Snapshot),而DAO則是動(dòng)態(tài)集(Dynaset)。
參數(shù)化的方式不同。DAO記錄集的m_strFilter和m_strSort中的參數(shù)不是“?”號(hào),而是一個(gè)有意義的參數(shù)名。例如,在下面的過(guò)濾器中有一個(gè)名為CourseIDParam的參數(shù)。
m_pSet->m_strFilter ="CourseID = CourseIDParam";
在DoFieldExchange函數(shù)中,有下面兩行:
pFX->SetFieldType(CDaoFieldExchange::param);
DFX_Text(pFX, _T("CourseIDParam"), m_strCourseIDParam);
DFX函數(shù)的第二個(gè)參數(shù)也是CourseIDParam。
處理異常的方式不同。例如,在刪除記錄時(shí),對(duì)異常的處理如下所示:
try
{
m_pSet->Delete();
}
catch(CDaoException* e)
{
AfxMessageBox(e->
m_pErrorInfo->m_strDescription);
e->Delete();
}
除了上述差別外,AppWizard和ClassWizard也隱藏了一些細(xì)微的不同之處,例如,DAO記錄集是使用是DFX數(shù)據(jù)交換機(jī)制(DAO record field exchange)而不是RFX,在DAO記錄集的DoFieldExchange中使用的是DFX函數(shù)而不是RFX函數(shù)。
10.8.3 DAO的特色
DAO可以通過(guò)ODBC驅(qū)動(dòng)程序訪問(wèn)ODBC數(shù)據(jù)源。但DAO是基于Microsoft Jet引擎的,通過(guò)該引擎,DAO可以直接訪問(wèn)Access、FoxPro、dBASE、Paradox、Excel和Lotus WK等數(shù)據(jù)庫(kù)。CDaoDatabase類(lèi)可以直接與這些數(shù)據(jù)庫(kù)進(jìn)行連接,而不必在ODBC管理器中注冊(cè)DSN。例如,下面的代碼用來(lái)打開(kāi)一個(gè)FoxPro數(shù)據(jù)庫(kù):
CDaoDatabase daoDb;
daoDb.Open( “”,FALSE,FALSE,"FoxPro 2.5;DATABASE=c://zyf");
CDaoDatabase::Open函數(shù)用來(lái)連接某個(gè)數(shù)據(jù)庫(kù),該函數(shù)的聲明為:
virtual void Open( LPCTSTR lpszName, BOOL bExclusive = FALSE, BOOL bReadOnly = FALSE, LPCTSTR lpszConnect = _T("") );
throw( CDaoException, CMemoryException );
參數(shù)bExclusive如果為TRUE,則函數(shù)以獨(dú)占方式打開(kāi)數(shù)據(jù)庫(kù),否則就用共享方式。如果bReadOnly為TRUE,那么就以只讀方式打開(kāi)數(shù)據(jù)庫(kù)。如果要打開(kāi)一個(gè)Access數(shù)據(jù)庫(kù),則可以在lpszName參數(shù)中指定MDB文件名。如果要訪問(wèn)非Access數(shù)據(jù)庫(kù),則應(yīng)使該參數(shù)為“”,并在lpszConnect中說(shuō)明一個(gè)連接字符串。連接字符串的形式一般為 “數(shù)據(jù)庫(kù)類(lèi)型;DATABASE=路徑(文件)”,例如 “dBASE III;DATABASE=c://MYDIR”
Open函數(shù)也可以打開(kāi)一個(gè)ODBC數(shù)據(jù)源,但這需要相應(yīng)的ODBC驅(qū)動(dòng)程序,并需要在ODBC管理器中注冊(cè)DSN。此時(shí)lpszConnect的形式為 “ODBC;DSN=MyDataSource”。顯然,用DAO訪問(wèn)象FoxPro這樣的數(shù)據(jù)庫(kù)時(shí),直接打開(kāi)比把它當(dāng)作ODBC數(shù)據(jù)源打開(kāi)要省事。
支持DDL是DAO對(duì)數(shù)據(jù)庫(kù)編程良好支持的一個(gè)重要體現(xiàn)。DDL(Data Definition Language)在SQL術(shù)語(yǔ)中叫做“數(shù)據(jù)定義語(yǔ)言”,它用來(lái)完成生成、修改和刪除數(shù)據(jù)庫(kù)結(jié)構(gòu)的操作。ODBC類(lèi)只支持DML(Data Manipulation Language,數(shù)據(jù)操作語(yǔ)言),不支持DDL,所以用ODBC類(lèi)只能完成數(shù)據(jù)的操作,不能涉及數(shù)據(jù)庫(kù)的結(jié)構(gòu)。要執(zhí)行DDL操作,只有通過(guò)ODBC API。而DAO類(lèi)同時(shí)提供了對(duì)DML和DDL的支持,這意味著程序可以使用DAO類(lèi)方便的創(chuàng)建數(shù)據(jù)庫(kù)及修改數(shù)據(jù)庫(kù)的結(jié)構(gòu)。
與ODBC相比,DAO提供了一些新類(lèi)來(lái)加強(qiáng)其功能,這些新類(lèi)包括:
CDaoTableDef類(lèi)提供了對(duì)表的結(jié)構(gòu)的定義。調(diào)用CDaoTableDef::Open可以獲得表的結(jié)構(gòu)定義。調(diào)用CDaoTableDef::Create可以創(chuàng)建一張新表,調(diào)用CDaoTableDef:: CreateField可為表添加字段,調(diào)用CDaoTableDef::CreateIndex可以為表添加索引。調(diào)用CDaoTableDef::Append可以把新創(chuàng)建的表保存到數(shù)據(jù)庫(kù)中。
CDaoQueryDef類(lèi)代表一個(gè)查詢定義(Query definition),該定義可以被存儲(chǔ)到數(shù)據(jù)庫(kù)中。
CDaoWorkspace提供了數(shù)據(jù)工作區(qū)(Workspace)。一個(gè)工作區(qū)可以包含幾個(gè)數(shù)據(jù)庫(kù),工作區(qū)可以對(duì)所屬的數(shù)據(jù)庫(kù)進(jìn)行全體或單獨(dú)的事務(wù)處理,工作區(qū)也負(fù)責(zé)數(shù)據(jù)庫(kù)的安全性。如果需要,程序可以打開(kāi)多個(gè)工作區(qū)。
DAO的另一個(gè)重要特色在于它對(duì)Access數(shù)據(jù)庫(kù)提供了強(qiáng)大的支持。由于DAO是基于Microsoft Jet引擎的,所以DAO肯定要在Access數(shù)據(jù)庫(kù)上多作一些文章。例如,調(diào)用CDaoDatabase::Create可以直接建立一個(gè)MDB文件,代碼如下所示:
m_db.Create(“C://MYDIR//MYDB.MDB”);
利用AppWizard和ClassWizard,用戶可以方便地開(kāi)發(fā)出性能優(yōu)良的基于DAO的Access數(shù)據(jù)庫(kù)應(yīng)用程序。
10.8.4 ODBC還是DAO
由于DAO可以訪問(wèn)ODBC數(shù)據(jù)源,下面幾條可以作為DAO替代ODBC的理由:
-
-
在某些情況下可以獲得更好的性能,特別是在訪問(wèn)Microsoft Jet(.MDB)數(shù)據(jù)庫(kù)時(shí)。
-
與ODBC兼容
-
DAO允許數(shù)據(jù)有效檢查
-
DAO允許用戶說(shuō)明表與表之間的關(guān)系
-
當(dāng)然,DAO的出現(xiàn)并不意味著ODBC已經(jīng)過(guò)時(shí)了。如果用戶的工作必須嚴(yán)格限于ODBC數(shù)據(jù)源,尤其是在開(kāi)發(fā)Client/Server結(jié)構(gòu)的應(yīng)用程序時(shí),用ODBC有較好的性能。
總結(jié)
- 上一篇: 有没有什么好的C++视频教程?
- 下一篇: 软件工程和计科专业对比,哪一个更适合毕业