版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)
文檔簡介
1、第14章 數(shù)據(jù)庫編程,14.1 ODBC的基本概念 14.2 MFC的ODBC類 14.3 創(chuàng)建一個ODBC數(shù)據(jù)源的數(shù)據(jù)庫管理程序?qū)嵗?14.4 深入理解CRecordset類,14.5 幾個有用的函數(shù) 14.6 增加程序的功能 14.7 DAO簡介 14.8 小結(jié) 習(xí)題,MFC提供了對數(shù)據(jù)庫編程的強大支持。對于數(shù)據(jù)庫的訪問,MFC提供了兩組類: ODBC(open database connectivity)和DAO(database access object)。利用這兩個功能強大的類,用戶可以方便地開發(fā)出基于ODBC或DAO的數(shù)據(jù)庫應(yīng)用。,ODBC(open database conne
2、ctivity,開放數(shù)據(jù)庫互連)是微軟公司開放服務(wù)結(jié)構(gòu)(windows open services architecture,WOSA)中有關(guān)數(shù)據(jù)庫的一個組成部分,它建立了一組規(guī)范,并提供了一組對數(shù)據(jù)庫訪問的標(biāo)準(zhǔn)API(應(yīng)用程序編程接口)。這些API利用SQL來完成其大部分任務(wù)。ODBC本身也提供了對SQL語言的支持,用戶可以直接將SQL語句送給ODBC。,14.1 ODBC的基本概念,一個基于ODBC的應(yīng)用程序?qū)?shù)據(jù)庫的操作不依賴任何DBMS(database manager system, 數(shù)據(jù)庫管理系統(tǒng)),不直接與DBMS打交道,所有的數(shù)據(jù)庫操作由對應(yīng)的DBMS的ODBC驅(qū)動程序完成。也
3、就是說,不論是FoxPro、Access還是Oracle數(shù)據(jù)庫,均可用ODBC API進行訪問。由此可見,ODBC的最大優(yōu)點是能以統(tǒng)一的方式處理所有的數(shù)據(jù)庫。,ODBC管理器(administrator)位于Windows控制面板(control panel)的32位ODBC內(nèi),其主要任務(wù)是管理安裝的ODBC驅(qū)動程序和管理數(shù)據(jù)源。 驅(qū)動程序管理器(driver manager)包含在ODBC32.DLL中,對用戶是透明的。其任務(wù)是管理ODBC驅(qū)動程序,是ODBC中最重要的部件。 ODBC 驅(qū)動程序是一些DLL,提供了ODBC和數(shù)據(jù)庫之間的接口。 數(shù)據(jù)源包含了數(shù)據(jù)庫位置和數(shù)據(jù)庫類型等信息,實際上
4、是一種數(shù)據(jù)連接的抽象。,應(yīng)用程序要訪問一個數(shù)據(jù)庫,首先必須用ODBC管理器注冊一個數(shù)據(jù)源,管理器根據(jù)數(shù)據(jù)源提供的數(shù)據(jù)庫位置、數(shù)據(jù)庫類型及ODBC驅(qū)動程序等信息,建立起ODBC與具體數(shù)據(jù)庫的聯(lián)系。這樣,只要應(yīng)用程序?qū)?shù)據(jù)源名提供給ODBC,ODBC就能建立起與相應(yīng)數(shù)據(jù)庫的連接。 在ODBC中,ODBC API不能直接訪問數(shù)據(jù)庫,必須通過驅(qū)動程序管理器與數(shù)據(jù)庫交換信息。驅(qū)動程序管理器負責(zé)將應(yīng)用程序?qū)DBC API的調(diào)用傳遞給正確的驅(qū)動程序,而驅(qū)動程序在執(zhí)行完相應(yīng)的操作后,將結(jié)果通過驅(qū)動程序管理器返回給應(yīng)用程序。在訪問ODBC數(shù)據(jù)源時需要ODBC驅(qū)動程序的支持。,MFC的ODBC類對較復(fù)雜的ODB
5、C API進行了封裝,提供了簡化的調(diào)用接口,從而大大方便了數(shù)據(jù)庫應(yīng)用程序的開發(fā)。程序員不必了解ODBC API和SQL的具體細節(jié),利用ODBC類即可完成對數(shù)據(jù)庫的大部分操作。,14.2 MFC的ODBC類,MFC的ODBC類主要包括: (1) CDatabase類, 主要功能是建立與數(shù)據(jù)源的連接。 (2) CRecordset類, 該類代表從數(shù)據(jù)源選擇的一組記錄(記錄集),程序可以選擇數(shù)據(jù)源中的某個表作為一個記錄集,也可以通過對表的查詢得到記錄集,還可以合并同一數(shù)據(jù)源中多個表的列到一個記錄集中。通過該類可對記錄集中的記錄進行滾動、修改、增加和刪除等操作。,(3) CRecordView類, 提
6、供了一個表單視圖與某個記錄集直接相連,利用對話框數(shù)據(jù)交換機制(DDX)在記錄集與表單視圖的控件之間傳輸數(shù)據(jù)。該類支持對記錄的瀏覽和更新,在撤銷時會自動關(guān)閉與之相聯(lián)系的記錄集。 (4) CFieldExchange類, 支持記錄字段數(shù)據(jù)交換(DFX),即記錄集字段數(shù)據(jù)成員與相應(yīng)的數(shù)據(jù)庫的表的字段之間的數(shù)據(jù)交換。該類的功能與CDataExchange類的對話框數(shù)據(jù)交換功能類似。 (5) CDBException類, 代表ODBC類產(chǎn)生的異常。,概括地講,CDatabase針對某個數(shù)據(jù)庫,它負責(zé)連接數(shù)據(jù)源; CRecordset針對數(shù)據(jù)源中的記錄集,它負責(zé)對記錄的操作; CRecordView負責(zé)界
7、面,而CFieldExchange負責(zé)CRecordset與數(shù)據(jù)源的數(shù)據(jù)交換。 利用AppWizard和ClassWizard,用戶可以方便地建立數(shù)據(jù)庫應(yīng)用程序,但這并不意味著可以對MFC的ODBC類一無所知。應(yīng)注意閱讀后面幾小節(jié)中的內(nèi)容,為學(xué)習(xí)后面的例子打好基礎(chǔ)。,要建立與數(shù)據(jù)源的連接,首先應(yīng)構(gòu)造一個CDatabase對象,然后再調(diào)用CDatabase的Open成員函數(shù)。Open函數(shù)負責(zé)建立連接,其聲明為: virtual BOOL Open( LPCTSTR lpszDSN, BOOL bExclusive = FALSE, BOOL bReadOnly = FALSE, LPCTSTR
8、lpszConnect = ODBC;, BOOL bUseCursorLib = TRUE ); throw( CDBException, CMemoryException );,14.2.1 CDatabase類,參數(shù)lpszDSN指定了數(shù)據(jù)源名,在lpszConnect參數(shù)中也可包括數(shù)據(jù)源名,此時lpszDSN必須為NULL,若在函數(shù)中未提供數(shù)據(jù)源名且使lpszDSN為NULL,則會顯示一個數(shù)據(jù)源對話框,用戶可以在該對話框中選擇一個數(shù)據(jù)源。參數(shù)bExclusive說明是否獨占數(shù)據(jù)源,由于目前版本的類庫還不支持獨占方式,故該參數(shù)的值應(yīng)該是FALSE,這說明數(shù)據(jù)源是被共享的。,參數(shù)bRead
9、Only若為TRUE則對數(shù)據(jù)源的連接是只讀的。參數(shù)lpszConnect指定了一個連接字符串,連接字符串中可以包括數(shù)據(jù)源名、用戶賬號(ID)和口令等信息,字符串中的“ODBC”表示要連接到一個ODBC數(shù)據(jù)源上。參數(shù)bUseCursorLib若為TRUE,則會裝載光標(biāo)庫,否則不裝載,快照需要光標(biāo)庫,動態(tài)集不需要光標(biāo)庫。若連接成功,函數(shù)返回TRUE,若返回FALSE,則說明用戶在數(shù)據(jù)源對話框中按了Cancel按鈕。若函數(shù)內(nèi)部出現(xiàn)錯誤,則框架會產(chǎn)生一個異常。,下面是一些調(diào)用Open函數(shù)的例子: CDatabase m_db; /在文檔類中嵌入一個CDatabase對象 /連接到一個名為Student
10、 Registration的數(shù)據(jù)源 m_db.Open(Student Registration); /在連接數(shù)據(jù)源的同時指定了用戶帳號和口令 m_db.Open(NULL,FALSE,FALSE,ODBC;DSN=Student Registration;UID=ZYF;PWD=1234); m_db.Open(NULL); /將彈出一個數(shù)據(jù)源對話框,要從一個數(shù)據(jù)源中脫離,可調(diào)用函數(shù)Close。在脫離后,可以再次調(diào)用Open函數(shù)來建立一個新的連接。調(diào)用IsOpen可判斷當(dāng)前是否有一個連接,調(diào)用GetConnect可返回當(dāng)前的連接字符串。函數(shù)的聲明為: virtual void Close(
11、); BOOL IsOpen( ) const; /返回TRUE則表明當(dāng)前有一個連接 const CString CDatabase的析構(gòu)函數(shù)會調(diào)用Close,所以只要刪除了CDatabase對象就可以與數(shù)據(jù)源脫離。,CRecordView(記錄視圖)是CFormView的派生類,它提供了一個表單視圖來顯示當(dāng)前記錄,用戶可以通過表單視圖顯示當(dāng)前記錄。通過記錄視圖,可以修改、添加和刪除數(shù)據(jù),用戶一般需要創(chuàng)建一個CRecordView的派生類,并在其對應(yīng)的對話框模板中加入控件。,14.2.2 CRecordView類,記錄視圖使用DDX數(shù)據(jù)交換機制在表單中的控件和記錄集之間交換數(shù)據(jù)。在前面介紹的D
12、DX都是在控件和控件父窗口的數(shù)據(jù)成員之間交換數(shù)據(jù),而記錄視圖則是在控件和一個外部對象(CRecordset的派生類對象)之間交換數(shù)據(jù)。清單顯示了一個CRecordView的派生類的DoDataExchange函數(shù),可以看出,該函數(shù)是與m_pSet指針指向的記錄集對象的域數(shù)據(jù)成員交換數(shù)據(jù)的。而且,交換數(shù)據(jù)的代碼是ClassWizard自動生成的。在后面的例子中,將介紹用ClassWizard連接記錄視圖與記錄集對象的方法。,在函數(shù)的開頭先調(diào)用CRecordset:Edit進入編輯模式,接著調(diào)用UpdateData將控件中的數(shù)據(jù)更新到記錄集對象的域數(shù)據(jù)成員中,然后調(diào)用CRecordset:Upda
13、te將域數(shù)據(jù)成員的值寫入數(shù)據(jù)源,這說明OnMove在滾動記錄的同時會完成對原來記錄的修改。 在函數(shù)的中間有一個分支語句用來處理4個不同的命令,在這個分支語句中調(diào)用了CRecordset的各種用于滾動記錄的成員函數(shù),這些函數(shù)在滾動到一個新的記錄時會把該記錄的內(nèi)容設(shè)置到域數(shù)據(jù)成員中。在函數(shù)的末尾調(diào)用UpdateData(FALSE)把新的當(dāng)前記錄的內(nèi)容設(shè)置到表單的控件中。,由此可見,OnMove一來一回完成了兩次表單控件和數(shù)據(jù)源的數(shù)據(jù)交換過程。通過分析該函數(shù),可以學(xué)會在瀏覽記錄時如何控制DDX和DFX數(shù)據(jù)交換。,例14.1 創(chuàng)建一個學(xué)生信息管理的數(shù)據(jù)庫應(yīng)用程序。 使用ODBC數(shù)據(jù)源,因此首先應(yīng)該創(chuàng)
14、建數(shù)據(jù)庫,這里采用Access 來創(chuàng)建,創(chuàng)建的步驟如下: (1) 運行Access,建立一個新數(shù)據(jù)庫,建立方法可以參考有關(guān)書籍。,14.3 創(chuàng)建一個ODBC數(shù)據(jù)源的數(shù)據(jù)庫管理程序?qū)嵗?(2) 數(shù)據(jù)庫創(chuàng)建完畢,就可以來創(chuàng)建ODBC數(shù)據(jù)源了,單擊計算機的“開始”按鈕,選擇“設(shè)置”“控制面板”命令,在彈出的控制面板對話框中,雙擊ODBC數(shù)據(jù)源圖標(biāo),如圖14.1所示。,圖14.1 在控制面板上創(chuàng)建ODBC數(shù)據(jù)源,此時,彈出圖14.2所示的對話框。,圖14.2 創(chuàng)建ODBC數(shù)據(jù)源,單擊“用戶DSN”選項卡中的“添加”按鈕,來創(chuàng)建一個Access類型的數(shù)據(jù)源,按照圖14.3所示對話框進行設(shè)置,選取上面建好
15、的數(shù)據(jù)庫,正如所看到的,將數(shù)據(jù)源的名稱取為“DSNSTUDENT”,這個名稱在下面進行程序設(shè)計時要用到。,圖14.3 設(shè)置數(shù)據(jù)源的名稱,(3) 做完這些準(zhǔn)備工作后,創(chuàng)建應(yīng)用程序的框架。遵循以下步驟: 運行AppWizard來創(chuàng)建一個MFC AppWizard的新項目,將其命名為“student”。 第一步,選擇基于Single document,語言支持中文。 第二步,選擇Database view with file support,并單擊Data Source按鈕,為程序指定圖14.4所示的數(shù)據(jù)源,集合類型選為Dynaset,單擊OK按鈕,在彈出的對話框中為程序選中可用的表“學(xué)生”(在本例
16、中,它是惟一可用的表),單擊OK按鈕,完成后單擊Next按鈕。,圖14.4 在創(chuàng)建應(yīng)用程序框架時指定數(shù)據(jù)源,第三步到第六步,保持默認設(shè)置,完成應(yīng)用程序的框架設(shè)計。 這時,可先停下來,認真看一下應(yīng)用程序向?qū)龅囊磺小I傻念愔杏袃牲c與以前的不一樣,一是類CStudentView,它由CRecordView類派生,而CRecordView類是CFormView的子類,它在CFormView類的基礎(chǔ)上添加了支持數(shù)據(jù)庫的功能,前面對它已有闡述; 二是CStudentSet類,它由CRecordSet類派生而來,關(guān)于CRecordSet類在前面已作過介紹。,(4) 進行窗體設(shè)計。在項目區(qū)中選擇類視圖區(qū)
17、展開Dialog,雙擊IDD_STUDENT_FORM編輯顯示的窗體,按圖14.5添加控件, 然后按表14.1來設(shè)置控件的屬性。(見書上表14.1),圖14.5 設(shè)計顯示數(shù)據(jù)庫數(shù)據(jù)的表單,將控件與變量進行關(guān)聯(lián),步驟如下: 運行類向?qū)В贛ember Variables選項卡中,選擇相應(yīng)的控件后單擊Add Variable按鈕。所需關(guān)聯(lián)的變量見表14.2。(見書上表14.2),程序中應(yīng)出現(xiàn)以下的代碼: void CStudentView:DoDataExchange(CDataExchange* pDX) CRecordView:DoDataExchange(pDX); /AFX_DATA_MA
18、P(CStudentView) / NOTE: the ClassWizard will add DDX and DDV calls here /AFX_DATA_MAP DDX_FieldText(pDX,IDC_EID,m_pSet-m_ID,m_pSet); DDX_FieldText(pDX,IDC_ENAME,m_pSet-m_name,m_pSet); DDX_FieldText(pDX,IDC_EZIP,m_pSet-m_zip,m_pSet);,DDX_FieldText(pDX,IDC_ETELEPHONE,m_pSet-m_telephone,m_pSet); DDX_Fi
19、eldText(pDX,IDC_ECITY,m_pSet-m_city,m_pSet); DDX_FieldText(pDX,IDC_EPROVINCE,m_pSet-m_province,m_pSet); DDX_FieldText(pDX,IDC_EADDRESS,m_pSet-m_address,m_pSet); DDX_FieldText(pDX,IDC_EMAJOR,m_pSet-m_major,m_pSet); ,上面的代碼體現(xiàn)了視圖中控件與變量的數(shù)據(jù)交換的機制。 此時調(diào)試運行程序,如果順利的話,應(yīng)該看到圖14.6所示的運行界面。在界面上,它與一般的單文檔應(yīng)用程序顯著的不同是在工具
20、欄上多了一組數(shù)據(jù)庫程序特有的按鈕,它們實現(xiàn)在數(shù)據(jù)庫記錄間的移動; 在菜單條中,也會多出“記錄”菜單項,打開這個菜單可以看到有4個子菜單,“第一個記錄”、“前一個記錄”、“下一個記錄”和“最后一個記錄”,它們分別對應(yīng)著前面所說的工具欄中4個按鈕。,圖14.6 程序的運行結(jié)果,此時,除了瀏覽記錄外,還可以修改記錄的內(nèi)容。這里值得注意的是,盡管在程序中已修改了記錄的內(nèi)容,但數(shù)據(jù)庫沒有立即更新,直到用戶移動了當(dāng)前記錄,才能實現(xiàn)數(shù)據(jù)庫的更新。,CRecordset類代表一個記錄集,該類是MFC的ODBC類中最重要、功能最強大的類之一。 記錄集主要分為快照(Snapshot) 和動態(tài)集(Dynaset)兩
21、種,CRecordset類對這兩者都支持。這兩種記錄集的不同,表現(xiàn)在它們對別的應(yīng)用改變數(shù)據(jù)源記錄采取了不同的處理方法。,14.4 深入理解CRecordset類,快照型記錄集提供了對數(shù)據(jù)的靜態(tài)視圖??煺帐莻€很形象的術(shù)語,就好像對數(shù)據(jù)源的某些記錄拍了一張照片一樣。當(dāng)別的用戶改變了記錄時(包括修改、添加和刪除),快照中的記錄不受影響。需要指出的是,快照的這種靜態(tài)特性是相對于別的用戶而言的,它會正確反映由本身用戶對記錄的修改和刪除,但對于新添加的記錄直到調(diào)用Requery后才能反映到快照中。,動態(tài)集提供了數(shù)據(jù)的動態(tài)視圖,當(dāng)別的用戶修改或刪除了記錄集中的記錄時,會在動態(tài)集中反映出來。當(dāng)滾動到修改過的記
22、錄時,對其所作的修改會立即反映到動態(tài)集中,當(dāng)記錄被刪除時,MFC代碼會跳過記錄集中的刪除部分,對于其他用戶添加的記錄,直到調(diào)用Requery時,才會在動態(tài)集中反映出來。本身應(yīng)用程序?qū)τ涗浀男薷?、添加和刪除會反映在動態(tài)集中。當(dāng)數(shù)據(jù)是動態(tài)的時候,使用動態(tài)集是最適合的。,快照和動態(tài)集有一個共同的特點,那就是在建立記錄集后,記錄集中的成員就已經(jīng)確定了,這就是為什么兩種記錄集都不能反映別的用戶添加記錄的原因。,本例中建立的是動態(tài)集類型的記錄集。見下面的代碼: CStudentSet:CStudentSet(CDatabase* pdb) : CRecordset(pdb) /AFX_FIELD_INIT
23、(CStudentSet) m_ID = 0; m_name = _T(); m_address = _T(); m_city = _T(); m_province = _T(); m_zip = _T(); m_telephone = _T(); m_major = _T();,m_numstu = 0; m_nFields = 9; /AFX_FIELD_INIT m_nDefaultType = dynaset; /記錄集的類型為動態(tài) CString CStudentSet:GetDefaultConnect() return _T(ODBC;DSN=DSNSTUDENT); /設(shè)置數(shù)據(jù)
24、源 CString CStudentSet:GetDefaultSQL() return _T(學(xué)生); /設(shè)置管理的數(shù)據(jù)表 ,CRecordset類代表一個記錄集,用戶一般需要用ClassWizard創(chuàng)建一個CRecordset的派生類。ClassWizard可以為派生的記錄集類創(chuàng)建一批數(shù)據(jù)成員,這些數(shù)據(jù)成員與記錄的各字段相對應(yīng),被稱為字段數(shù)據(jù)成員或域數(shù)據(jù)成員。域數(shù)據(jù)成員用來保存某條記錄的各個字段,它們是程序與記錄之間的緩沖區(qū)。域數(shù)據(jù)成員代表當(dāng)前記錄,當(dāng)在記錄集中滾動到某一記錄時,框架自動地把記錄的各個字段拷貝到記錄集對象的域數(shù)據(jù)成員中,當(dāng)用戶要修改當(dāng)前記錄或增加新記錄時,程序先將各字段的新
25、值放入域數(shù)據(jù)成員中,然后調(diào)用相應(yīng)的CRecordset成員函數(shù)把域數(shù)據(jù)成員設(shè)置到數(shù)據(jù)源中。,因此,在記錄集與數(shù)據(jù)源之間有一個數(shù)據(jù)交換問題。CRecordset類使用“記錄域交換”( Record Field Exchange,縮寫為RFX)機制自動地在域數(shù)據(jù)成員和數(shù)據(jù)源之間交換數(shù)據(jù)。RFX機制與對話數(shù)據(jù)交換(DDX)類似,CRecordset的成員函數(shù)DoFieldExchange負責(zé)數(shù)據(jù)交換任務(wù),在該函數(shù)中調(diào)用了一系列RFX函數(shù),一般由ClassWizard自動建立。下面是本例中為數(shù)據(jù)交換建立的代碼: void CStudentSet:DoFieldExchange(CFieldExchan
26、ge* pFX) ,/AFX_FIELD_MAP(CStudentSet) pFX-SetFieldType(CFieldExchange:outputColumn); RFX_Long(pFX, _T(ID), m_ID); RFX_Text(pFX, _T(name), m_name); RFX_Text(pFX, _T(address), m_address); RFX_Text(pFX, _T(city), m_city); RFX_Text(pFX, _T(province), m_province); RFX_Text(pFX, _T(zip), m_zip); RFX_Text(
27、pFX, _T(telephone), m_telephone); RFX_Text(pFX, _T(major), m_major); RFX_Long(pFX, _T(numstu), m_numstu); /AFX_FIELD_MAP ,CRecordset提供了幾個成員函數(shù)用來在記錄集中滾動,當(dāng)用這些函數(shù)滾動到一個新記錄時,框架會自動地把新記錄的內(nèi)容拷貝到域數(shù)據(jù)成員中。 void MoveNext() 前進一個記錄; void MovePrev() 后退一個記錄; void MoveFirst() 滾動到記錄集中的第一個記錄; void MoveLast() 滾動到記錄集中的最后一個記
28、錄; void SetAbsolutePosition( long nRows ),該函數(shù)用于滾動到由參數(shù)nRows指定的絕對位置處;,14.5 幾個有用的函數(shù),BOOL IsEOF() const如果記錄集為空或滾動過了最后一個記錄,那么函數(shù)返回TRUE,否則返回FALSE; BOOL IsBOF() const 如果記錄集為空或滾動過了第一個記錄,那么函數(shù)返回TRUE,否則返回FALSE。,上面的程序總還缺少點什么。下面,為程序添加兩個功能,記錄的添加和記錄的刪除。實現(xiàn)這兩個功能,有必要接著上文講一下記錄添加和刪除的實現(xiàn)。,14.6 增加程序的功能,要向記錄集中添加新的記錄,應(yīng)該按下列步驟
29、進行: (1) 調(diào)用AddNew成員函數(shù)進入添加模式,該函數(shù)把所有的域數(shù)據(jù)成員都設(shè)置成NULL(注意,在數(shù)據(jù)庫術(shù)語中,NULL是指沒有值,這與C+的NULL是不同的)。與Edit一樣,AddNew會把當(dāng)前域數(shù)據(jù)成員的內(nèi)容保存在一個緩沖區(qū)中,在必要的時候,程序可以再次調(diào)用AddNew取消添加操作并恢復(fù)域數(shù)據(jù)成員原來的值,調(diào)用后程序仍處于添加模式,調(diào)用Move(AFX_MOVE_REFRESH)可退出添加模式,同時該函數(shù)會從緩沖區(qū)中恢復(fù)域數(shù)據(jù)成員。,(2) 調(diào)用Update把域數(shù)據(jù)成員中的內(nèi)容作為新記錄寫入數(shù)據(jù)源,從而結(jié)束添加。 如果記錄集是快照,那么在添加一個新的記錄后,需要調(diào)用Requery重
30、新查詢,因為快照無法反映添加操作。,要刪除記錄集的當(dāng)前記錄,應(yīng)按下面兩步進行: (1) 調(diào)用Delete成員函數(shù),該函數(shù)會同時給記錄集和數(shù)據(jù)源中當(dāng)前記錄加上刪除標(biāo)記。注意不要在一個空記錄集中調(diào)用Delete,否則會產(chǎn)生一個異常。 (2) 滾動到另一個記錄上以跳過刪除記錄。,上面提到的函數(shù)聲明為: virtual void AddNew( );throw( CDBException ); virtual void Delete( );throw( CDBException ); virtual BOOL Update( );throw( CDBException ); 若更新失敗則函數(shù)返回FAL
31、SE,且會產(chǎn)生一個異常。,在對記錄集進行更改以前,程序也許要調(diào)用下列函數(shù)來判斷記錄集是否可以更改,因為如果在不能更改的記錄集中進行修改、添加或刪除將導(dǎo)致異常的產(chǎn)生。 BOOL CanUpdate( ) const; /返回TRUE表明記錄是可以修改、添加和刪除的。 BOOL CanAppend( ) const; /返回TRUE則表明可以添加記錄。,本例中,在進行記錄的添加時,有一個需要注意的問題,因為在數(shù)據(jù)表的設(shè)計時將編號作為記錄的主關(guān)鍵字,這要求在添加記錄時,每兩個記錄的編號項不能相同??梢酝ㄟ^設(shè)置編號所對應(yīng)的文本框的屬性來解決這個問題,凍結(jié)文本框的可編輯功能,使之只用于顯示,編號由程序自
32、動添加。在窗體設(shè)計的環(huán)境下右擊編號所對應(yīng)的文本框,在彈出的屬性框中核選Disabled選項。,添加和刪除功能采用菜單驅(qū)動,為此需要編輯菜單資源,方法與以前相同。增加兩個菜單和一個分隔欄,如圖14.7所示,菜單屬性設(shè)計見表14.3。,圖14.7 設(shè)計菜單,表14.3 設(shè)置菜單的屬性,為菜單映射函數(shù),方法在前文已有闡述。編輯下面的代碼: void CStudentView:OnAdd() / TODO: Add your command handler code here CRecordset * pset = OnGetRecordset(); /保存當(dāng)前記錄的任何變化 if (pset-Can
33、Update() ,/獲取新記錄的ID號 long m_lnewID=m_pSet-GetMaxID()+1; /添加新記錄 m_pSet-AddNew(); m_pSet-m_ID=m_lnewID; /保存新記錄 m_pSet-Update(); /更新記錄集 m_pSet-Requery(); m_pSet-MoveLast(); /更新顯示窗體 UpdateData(FALSE); ,void CStudentView:OnDelrec() / TODO: Add your command handler code here if (MessageBox(Are you sure yo
34、u want to delete this record?, Delete this record?,MB_YESNOCANCEL | MB_ICONQUESTION)=IDYES), /刪除當(dāng)前記錄 m_pSet-Delete(); /數(shù)據(jù)記錄指針前移 m_pSet-MovePrev(); /更新數(shù)據(jù) UpdateData(FALSE); ,除了ODBC 類,MFC也提供了一組DAO(database access object)類,也可以用來創(chuàng)建數(shù)據(jù)庫應(yīng)用程序。DAO在很大程度上是ODBC 類的超集,它包含了ODBC 類的大部分功能。與ODBC一樣,DAO提供了一組API供編程使用,從而大
35、大簡化了程序的開發(fā)。利用MFC的DAO類,用戶可以編寫?yīng)毩⒂贒BMS的應(yīng)用程序。,14.7 DAO簡介,DAO類與ODBC類相比具有很多相似之處。首先,二者都支持對各種ODBC數(shù)據(jù)源的訪問。雖然二者使用的數(shù)據(jù)引擎不同,但都可以滿足用戶編寫?yīng)毩⒂贒BMS的應(yīng)用程序的要求; 其次,DAO提供了與ODBC功能相似的MFC類,它們的大部分成員函數(shù)都是相同的。,由于DAO類使用了微軟Jet數(shù)據(jù)庫引擎,與ODBC類十分相似,因此只要掌握了ODBC,就很容易學(xué)會使用DAO。實際上,可以很輕松地把數(shù)據(jù)庫應(yīng)用程序從ODBC移植到DAO,只需要將程序中使用的類的名字對應(yīng)到DAO中。即CDatabase 改為CDa
36、oDatabase, CRecordset 改為CDaoRecordset, CRecordView 改為CDaoRecordView。,在ODBC 和DAO之間還有許多不同的地方。其中,一個較大的不同是系統(tǒng)實現(xiàn)函數(shù)的方法不同,ODBC 使用一組DLL實現(xiàn),而DAO使用OLE對象來實現(xiàn)。 一般地講,DAO類提供了比ODBC類更廣泛的支持。一方面,只要有ODBC驅(qū)動程序,使用Microsoft Jet的DAO就可以訪問ODBC數(shù)據(jù)源。另一方面,由于DAO是基于Microsoft Jet引擎的,因而在訪問Access數(shù)據(jù)庫(即*.MDB文件)時具有很好的性能,但在訪問其他類型的庫時,效率不是很高。
37、,還有以下的不同之處: (1) 記錄集的默認類型不同。ODBC記錄集的默認類型是快照(Snapshot),而DAO默認類型則是動態(tài)集(Dynaset)。 (2) 參數(shù)化的方式不同。DAO記錄集的m_strFilter和m_strSort中的參數(shù)不是“?”號,而是一個有意義的參數(shù)名。,例如,在下面的過濾器中有一個名為CourseIDParam的參數(shù): m_pSet-m_strFilter =CourseID = CourseIDParam; 在DoFieldExchange函數(shù)中,有下面兩行: pFX-SetFieldType(CDaoFieldExchange:param); DFX_Text
38、(pFX, _T(CourseIDParam), m_strCourseIDParam); DFX函數(shù)的第二個參數(shù)也是CourseIDParam。,(3) 處理異常的方式不同。例如,在刪除記錄時,對異常的處理如下所示: try m_pSet-Delete(); catch(CDaoException* e) AfxMessageBox(e- m_pErrorInfo-m_strDescription); e-Delete(); ,DAO記錄集是使用是DFX數(shù)據(jù)交換機制(DAO record field exchange)而不是RFX,在DAO記錄集的DoFieldExchange中, 使用的是
39、DFX函數(shù)而不是RFX函數(shù)。,DAO可以通過ODBC驅(qū)動程序訪問ODBC數(shù)據(jù)源。但DAO是基于Microsoft Jet引擎的,通過該引擎,DAO可以直接訪問Access、FoxPro、dBASE、Paradox、Excel和Lotus WK等數(shù)據(jù)庫。CDaoDatabase類可以直接與這些數(shù)據(jù)庫進行連接,而不必在ODBC管理器中注冊DSN。例如,下面的代碼用來打開一個FoxPro數(shù)據(jù)庫: CDaoDatabase daoDb; daoDb.Open( “”,FALSE,FALSE,FoxPro 2.5;DATABASE=c:zyf);,CDaoDatabase:Open函數(shù)用來連接某個數(shù)據(jù)庫
40、,該函數(shù)的聲明為: virtual void Open( LPCTSTR lpszName, BOOL bExclusive = FALSE, BOOL bReadOnly = FALSE, LPCTSTR lpszConnect = _T() ); throw( CDaoException, CMemoryException );,參數(shù)bExclusive如果為TRUE,則函數(shù)以獨占方式打開數(shù)據(jù)庫,否則就用共享方式。如果bReadOnly為TRUE,那么就以只讀方式打開數(shù)據(jù)庫。如果要打開一個Access數(shù)據(jù)庫,則可以在lpszName參數(shù)中指定MDB文件名。如果要訪問非Access數(shù)據(jù)庫,則
41、應(yīng)使該參數(shù)為“”,并在lpszConnect中說明一個連接字符串。連接字符串的形式一般為“數(shù)據(jù)庫類型; DATABASE=路徑(文件)”,例如“dBASE ;DATABASE=c:MYDIR”。,Open函數(shù)也可以打開一個ODBC數(shù)據(jù)源,但這需要相應(yīng)的ODBC驅(qū)動程序,并需要在ODBC管理器中注冊DSN。此時lpszConnect的形式為“ODBC;DSN=MyDataSource”。顯然,用DAO訪問象FoxPro這樣的數(shù)據(jù)庫時,直接打開比把它當(dāng)作ODBC數(shù)據(jù)源打開要省事。,支持DDL是DAO對數(shù)據(jù)庫編程良好支持的一個重要體現(xiàn)。DDL(data definition language)在SQ
42、L術(shù)語中叫做“數(shù)據(jù)定義語言”,它用來完成生成、修改和刪除數(shù)據(jù)庫結(jié)構(gòu)的操作。ODBC類只支持DML(data manipulation language,數(shù)據(jù)操作語言),不支持DDL,所以用ODBC類只能完成數(shù)據(jù)的操作,不能涉及數(shù)據(jù)庫的結(jié)構(gòu)。要執(zhí)行DDL操作,只有通過ODBC API。而DAO類同時提供了對DML和DDL的支持,這意味著程序可以使用DAO類方便地創(chuàng)建數(shù)據(jù)庫及修改數(shù)據(jù)庫的結(jié)構(gòu)。,與ODBC相比,DAO提供了一些新類來加強其功能,這些新類包括: CDaoTableDef類提供了對表的結(jié)構(gòu)的定義。調(diào)用CDaoTableDef:Open可以獲得表的結(jié)構(gòu)定義, 調(diào)用CDaoTableDef
43、:Create可以創(chuàng)建一張新表,調(diào)用CDaoTableDef: CreateField可為表添加字段,調(diào)用CDaoTableDef:CreateIndex可以為表添加索引, 調(diào)用CDaoTableDef:Append可以把新創(chuàng)建的表保存到數(shù)據(jù)庫中。,CDaoQueryDef類代表一個查詢定義(Query definition),該定義可以被存儲到數(shù)據(jù)庫中。 CDaoWorkspace提供了數(shù)據(jù)工作區(qū)(Workspace)。一個工作區(qū)可以包含幾個數(shù)據(jù)庫,工作區(qū)可以對所屬的數(shù)據(jù)庫進行全體或單獨的事務(wù)處理,工作區(qū)也負責(zé)數(shù)據(jù)庫的安全性。如果需要,程序可以打開多個工作區(qū)。,DAO的另一個重要特色在于它對
44、Access數(shù)據(jù)庫提供了強大的支持。由于DAO是基于Microsoft Jet引擎的,所以DAO肯定要在Access數(shù)據(jù)庫上多做一些文章。例如,調(diào)用CDaoDatabase:Create可以直接建立一個MDB文件,代碼如下所示: m_db.Create(d:zdmstudent.mdb); 利用AppWizard和ClassWizard,用戶可以方便地開發(fā)出性能優(yōu)良的基于DAO的Access數(shù)據(jù)庫應(yīng)用程序。,由于DAO可以訪問ODBC數(shù)據(jù)源,下面幾條可以作為DAO替代ODBC的理由: 在某些情況下可以獲得更好的性能,特別是在訪問Microsoft Jet(.MDB)數(shù)據(jù)庫時與ODBC兼容; DAO允許數(shù)據(jù)有效檢查
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 2026年房地產(chǎn)市場中的臨時推廣活動有效性分析
- 2026年端午節(jié)的民族特色清明節(jié)的緬懷與回憶
- 2025年陜西白水人事考試及答案
- 2025年智聯(lián)招聘事業(yè)單位要考試及答案
- 2025年社工人事考試及答案
- 2025年扶余事業(yè)編歷年考試真題及答案
- 2025年廈門市藥學(xué)類事業(yè)編考試及答案
- 2025年淮安盱眙衛(wèi)生事業(yè)編考試及答案
- 2026年圖書館信息素養(yǎng)培訓(xùn)
- 湖北某國有人才集團招聘外包工作人員3人筆試備考試題及答案解析
- 對賬單模板完整版本
- 介紹壁球班課件
- 工業(yè)互聯(lián)網(wǎng)安全技術(shù)(微課版)課件全套 項目1-7 工業(yè)互聯(lián)網(wǎng)及安全認識-工業(yè)互聯(lián)網(wǎng)安全新技術(shù)認識
- 甲狀腺乳腺外科診療規(guī)范
- 退換貨方案及措施
- 麻醉科常用耗材分類與管理要點
- 材料力學(xué)性能檢驗工安全教育培訓(xùn)手冊
- 小說影視化改編的深度解析
- JJF 2214-2025 機動車檢測用氣象單元校準(zhǔn)規(guī)范
- 嚴格招標(biāo)需求管理制度
- 外科洗手操作標(biāo)準(zhǔn)與流程
評論
0/150
提交評論