一、實(shí)現(xiàn)方法
DAO(Database Access Object)使用Microsoft Jet數(shù)據(jù)庫(kù)引擎來(lái)訪(fǎng)問(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),用戶(hù)可以編寫(xiě)?yīng)毩⒂贒BMS的應(yīng)用程序。
DAO是從Visual C++4.0版開(kāi)始引入的。一般地講,DAO類(lèi)提供了比ODBC類(lèi)更廣泛的支持。一方面,只要有ODBC驅(qū)動(dòng)程序,使用Microsoft Jet的DAO就可以訪(fǎng)問(wèn)ODBC數(shù)據(jù)源。另一方面,由于DAO是基于Microsoft Jet引擎的,因而在訪(fǎng)問(wèn)Access數(shù)據(jù)庫(kù)(即*.MDB文件)時(shí)具有很好的性能。DAO類(lèi)與ODBC類(lèi)相比具有很多相似之處,這主要有下面幾點(diǎn):(1)二者都支持對(duì)各種ODBC數(shù)據(jù)源的訪(fǎng)問(wèn)。雖然二者使用的數(shù)據(jù)引擎不同,但都可以滿(mǎn)足用戶(hù)編寫(xiě)?yīng)毩⒂贒BMS的應(yīng)用程序的要求。(2)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ù)都是相同的。(3)AppWizard和ClassWizard對(duì)使用DAO和ODBC對(duì)象的應(yīng)用程序提供了類(lèi)似的支持。
由于DAO和ODBC類(lèi)的許多方面都比較相似,因此只要用戶(hù)掌握了ODBC,就很容易學(xué)會(huì)使用DAO。實(shí)際上,用戶(hù)可以很輕松地把數(shù)據(jù)庫(kù)應(yīng)用程序從ODBC移植到DAO。需要注意的是,DAO和ODBC參數(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。
除了上述差別外,AppWizard和ClassWizard也隱藏了一些細(xì)微的不同之處,例如,DAO記錄集是使用是DFX數(shù)據(jù)交換機(jī)制(DAO record field exchange)而不是RFX,在DAO記錄集的DoFieldExchange中使用的是DFX函數(shù)而不是RFX函數(shù)。
DAO可以通過(guò)ODBC驅(qū)動(dòng)程序訪(fǎng)問(wèn)ODBC數(shù)據(jù)源。但DAO是基于Microsoft Jet引擎的,通過(guò)該引擎,DAO可以直接訪(fǎng)問(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如果為T(mén)RUE,則函數(shù)以獨(dú)占方式打開(kāi)數(shù)據(jù)庫(kù),否則就用共享方式。如果bReadOnly為T(mén)RUE,那么就以只讀方式打開(kāi)數(shù)據(jù)庫(kù)。如果要打開(kāi)一個(gè)Access數(shù)據(jù)庫(kù),則可以在lpszName參數(shù)中指定MDB文件名。如果要訪(fǎng)問(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訪(fǎng)問(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()函數(shù)可以獲得表的結(jié)構(gòu)定義。調(diào)用CDaoTableDef::Create()函數(shù)可以創(chuàng)建一張新表,調(diào)用CDaoTableDef:: CreateField()函數(shù)可為表添加字段,調(diào)用CDaoTableDef::CreateIndex()函數(shù)可以為表添加索引。調(diào)用CDaoTableDef::Append()函數(shù)可以把新創(chuàng)建的表保存到數(shù)據(jù)庫(kù)中。
CDaoQueryDef類(lèi)代表一個(gè)查詢(xún)定義(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()函數(shù)可以直接建立一個(gè)MDB文件,代碼如下所示:
m_db.Create("C:\\MYDIR\\MYDB.MDB");
利用AppWizard和ClassWizard,用戶(hù)可以方便地開(kāi)發(fā)出性能優(yōu)良的基于DAO的Access數(shù)據(jù)庫(kù)應(yīng)用程序。
DAO(Database Access Object)使用Microsoft Jet數(shù)據(jù)庫(kù)引擎來(lái)訪(fǎng)問(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),用戶(hù)可以編寫(xiě)?yīng)毩⒂贒BMS的應(yīng)用程序。
DAO是從Visual C++4.0版開(kāi)始引入的。一般地講,DAO類(lèi)提供了比ODBC類(lèi)更廣泛的支持。一方面,只要有ODBC驅(qū)動(dòng)程序,使用Microsoft Jet的DAO就可以訪(fǎng)問(wèn)ODBC數(shù)據(jù)源。另一方面,由于DAO是基于Microsoft Jet引擎的,因而在訪(fǎng)問(wèn)Access數(shù)據(jù)庫(kù)(即*.MDB文件)時(shí)具有很好的性能。DAO類(lèi)與ODBC類(lèi)相比具有很多相似之處,這主要有下面幾點(diǎn):(1)二者都支持對(duì)各種ODBC數(shù)據(jù)源的訪(fǎng)問(wèn)。雖然二者使用的數(shù)據(jù)引擎不同,但都可以滿(mǎn)足用戶(hù)編寫(xiě)?yīng)毩⒂贒BMS的應(yīng)用程序的要求。(2)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ù)都是相同的。(3)AppWizard和ClassWizard對(duì)使用DAO和ODBC對(duì)象的應(yīng)用程序提供了類(lèi)似的支持。
由于DAO和ODBC類(lèi)的許多方面都比較相似,因此只要用戶(hù)掌握了ODBC,就很容易學(xué)會(huì)使用DAO。實(shí)際上,用戶(hù)可以很輕松地把數(shù)據(jù)庫(kù)應(yīng)用程序從ODBC移植到DAO。需要注意的是,DAO和ODBC參數(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。
除了上述差別外,AppWizard和ClassWizard也隱藏了一些細(xì)微的不同之處,例如,DAO記錄集是使用是DFX數(shù)據(jù)交換機(jī)制(DAO record field exchange)而不是RFX,在DAO記錄集的DoFieldExchange中使用的是DFX函數(shù)而不是RFX函數(shù)。
DAO可以通過(guò)ODBC驅(qū)動(dòng)程序訪(fǎng)問(wèn)ODBC數(shù)據(jù)源。但DAO是基于Microsoft Jet引擎的,通過(guò)該引擎,DAO可以直接訪(fǎng)問(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如果為T(mén)RUE,則函數(shù)以獨(dú)占方式打開(kāi)數(shù)據(jù)庫(kù),否則就用共享方式。如果bReadOnly為T(mén)RUE,那么就以只讀方式打開(kāi)數(shù)據(jù)庫(kù)。如果要打開(kāi)一個(gè)Access數(shù)據(jù)庫(kù),則可以在lpszName參數(shù)中指定MDB文件名。如果要訪(fǎng)問(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訪(fǎng)問(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()函數(shù)可以獲得表的結(jié)構(gòu)定義。調(diào)用CDaoTableDef::Create()函數(shù)可以創(chuàng)建一張新表,調(diào)用CDaoTableDef:: CreateField()函數(shù)可為表添加字段,調(diào)用CDaoTableDef::CreateIndex()函數(shù)可以為表添加索引。調(diào)用CDaoTableDef::Append()函數(shù)可以把新創(chuàng)建的表保存到數(shù)據(jù)庫(kù)中。
CDaoQueryDef類(lèi)代表一個(gè)查詢(xún)定義(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()函數(shù)可以直接建立一個(gè)MDB文件,代碼如下所示:
m_db.Create("C:\\MYDIR\\MYDB.MDB");
利用AppWizard和ClassWizard,用戶(hù)可以方便地開(kāi)發(fā)出性能優(yōu)良的基于DAO的Access數(shù)據(jù)庫(kù)應(yīng)用程序。