備註
DAO 與 Access 資料庫搭配使用,並透過 Office 2013 支援。 DAO 3.6 是最終版本,而且被視為過時。 Visual C++ 環境和精靈不支援 DAO(雖然包含 DAO 類別,您仍然可以使用這些類別)。 Microsoft建議您針對新專案使用 OLE DB 範本 或 ODBC 和 MFC 。 您應該只使用 DAO 來維護現有的應用程式。
此技術備忘錄描述 DAO 記錄欄位交換(DFX)機制。 為了協助瞭解 DFX 例程中發生的情況, DFX_Text 函式將詳細說明為範例。 作為此技術注意事項的其他資訊來源,您可以檢查其他個別 DFX 函式的程式碼。 您可能不需要自定義 DFX 例程,因為您可能需要自定義 RFX 例程(搭配 ODBC 資料庫類別使用)。
此技術附註包含:
DFX 概觀
使用 DAO 記錄欄位交換和動態系結的範例
DFX 概觀
DAO 記錄欄位交換機制 (DFX) 可用來簡化使用 CDaoRecordset 類別時擷取和更新數據的程式。 使用類別的數據成員 CDaoRecordset 來簡化此程式。 藉由衍生自 CDaoRecordset,您可以將數據成員加入衍生類別,代表數據表或查詢中的每個字段。 這個「靜態系結」機制很簡單,但可能不是所有應用程式選擇的數據擷取/更新方法。 每次變更當前記錄時,DFX 會擷取每個系結字段。 如果您要開發效能敏感的應用程式,在變更貨幣時不需要擷取每個欄位,則透過 「動態系結」CDaoRecordset::GetFieldValueCDaoRecordset::SetFieldValue可能是選擇的數據存取方法。
備註
DFX 和動態系結並非互斥,因此可以使用靜態和動態系結的混合式用法。
範例 1 - 僅使用 DAO 記錄欄位交換
(假設 CDaoRecordset — 衍生類別 CMySet 已經開啟)
// Add a new record to the customers table
myset.AddNew();
myset.m_strCustID = _T("MSFT");
myset.m_strCustName = _T("Microsoft");
myset.Update();
範例 2 - 僅使用動態系結
(假設使用 CDaoRecordset 類別, rs且它已經開啟)
// Add a new record to the customers table
COleVariant varFieldValue1 (_T("MSFT"),
VT_BSTRT);
//Note: VT_BSTRT flags string type as ANSI,
instead of UNICODE default
COleVariant varFieldValue2 (_T("Microsoft"),
VT_BSTRT);
rs.AddNew();
rs.SetFieldValue(_T("Customer_ID"),
varFieldValue1);
rs.SetFieldValue(_T("Customer_Name"),
varFieldValue2);
rs.Update();
範例 3 - 使用 DAO 記錄字段交換和動態系結
(假設使用 CDaoRecordset衍生類別 emp瀏覽員工資料)
// Get the employee's data so that it can be displayed
emp.MoveNext();
// If user wants to see employee's photograph,
// fetch it
COleVariant varPhoto;
if (bSeePicture)
emp.GetFieldValue(_T("photo"),
varPhoto);
// Display the data
PopUpEmployeeData(emp.m_strFirstName,
emp.m_strLastName,
varPhoto);
DFX 的運作方式
DFX 機制的運作方式與 MFC ODBC 類別所使用的記錄欄位交換 (RFX) 機制類似。 DFX 和 RFX 的原則相同,但有許多內部差異。 DFX 函式的設計使得幾乎所有程式碼都由個別的 DFX 例程共用。 在最高層級,DFX 只執行少數幾項功能。
DFX 會在必要時建構 SQL SELECT 子句和 SQL PARAMETERS 子句。
DFX 會建構 DAO 函
GetRows式所使用的系結結構(稍後會進一步說明)。DFX 會管理用來偵測髒字段的數據緩衝區(如果使用雙緩衝處理)
DFX 會管理 NULL 和 DIRTY 狀態陣列,並在更新時視需要設定值。
DFX 機制的核心是 CDaoRecordset 衍生類別的函 DoFieldExchange 式。 此函式會將呼叫分派至適當操作類型的各個 DFX 函式。 呼叫 DoFieldExchange 內部 MFC 函式之前,請先設定作業類型。 下列清單顯示各種作業類型和簡短描述。
| 行動 | 說明 |
|---|---|
AddToParameterList |
建立PARAMETERS子句 |
AddToSelectList |
建置 SELECT 子句 |
BindField |
設定綁定結構 |
BindParam |
設定參數值 |
Fixup |
設定 NULL 狀態 |
AllocCache |
配置快取以進行骯髒檢查 |
StoreField |
將當前記錄儲存至快取 |
LoadField |
將快取還原為成員值 |
FreeCache |
釋放快取 |
SetFieldNull |
將欄位狀態和值設定為 NULL |
MarkForAddNew |
如果欄位不是 PSEUDO NULL,則標記為已變更 |
MarkForEdit |
如果欄位內容不符合快取,則標記為已變更 |
SetDirtyField |
設定被標示為已變更的欄位值 |
在下一節中,將更詳細地說明DFX_Text的每個作業。
瞭解 DAO 記錄欄位交換過程的最重要特點是,它會使用 GetRows 物件的 CDaoRecordset 函式。 DAO GetRows 函式可以透過數種方式運作。 此技術附注只會簡短描述 GetRows ,因為它超出此技術附注的範圍。
DAO GetRows 可以透過數種方式運作。
它可以一次擷取多個記錄和多個數據欄位。 這讓您能更快速地存取數據,但也帶來了處理大型數據結構的複雜性,以及為結構中每個欄位和數據記錄找到適當位移的挑戰。 MFC 不會利用該多個記錄擷取機制。
另一種方法
GetRows是允許程式設計人員針對一筆數據記錄指定每個欄位所擷取數據的系結位址。DAO 也會「回呼」至呼叫端的可變長度欄位,以允許呼叫端分配記憶體。 第二個功能的優點是將數據復本數目降至最低,並允許將數據直接儲存到類別的成員(
CDaoRecordset衍生類別)。 MFC 用的第二個機制是將CDaoRecordset類別中的資料成員系結至衍生類別的方法。
自定義 DFX 例程的功能
從這個討論中很明顯,任何 DFX 函式中實作的最重要作業都必須能夠設定必要的資料結構,才能成功呼叫 GetRows。 還有一些其他作業,DFX 函式也必須支援,但沒有一個像正確準備 GetRows 呼叫一樣重要或複雜。
DFX 的使用說明於在線檔中。 基本上,有兩個需求。 首先,必須將成員添加至每個綁定欄位和參數的 CDaoRecordset 衍生類別。 接下來這個 CDaoRecordset::DoFieldExchange 應該被覆寫。 請注意,成員的數據類型很重要。 它應該符合資料庫中欄位的數據,或至少可轉換成該類型。 例如,資料庫中的數值欄位,例如長整數,一律可以轉換成文字並系結至 CString 成員,但資料庫中的文字欄位不一定轉換成數值表示法,例如長整數並系結至長整數成員。 DAO 和 Microsoft Jet 資料庫引擎負責轉換 (而不是 MFC)。
DFX_Text的詳細數據
如先前所述,說明 DFX 運作方式的最佳方式是透過範例運作。 為了達成此目的,探討 DFX_Text 的內部運作應該能夠相當有效地協助提供對 DFX 的基本瞭解。
AddToParameterList這項作業會建置 Jet 所需的 SQL PARAMETERS 子句 (“”
Parameters <param name>, <param type> ... ;)。 每個參數都會命名並輸入 (如 RFX 呼叫中所指定)。 請參閱函式CDaoFieldExchange::AppendParamType函式,以查看個別類型的名稱。 在 的案例DFX_Text中,所使用的類型為 文字。AddToSelectList建置 SQL SELECT 子句。 DFX 呼叫指定的欄位名稱會被直接附加在後面(即 "
SELECT <column name>, ...")。BindField作業最複雜。 如先前所述,這是設定
GetRows所使用的DAO綁定結構的位置。 如您所見,從DFX_Text的程式碼可知,結構中的資訊類型包括使用的 DAO 類型(在的情況下為DAO_CHAR或DFX_Text)。 此外,也會設定所使用的系結類型。 在先前的章節GetRows中,只簡短說明 MFC 所使用的系結類型一律是直接地址系結(DAOBINDING_DIRECT)。 此外,對於可變長度欄位綁定(例如DFX_Text),會使用回呼綁定以讓 MFC 可以控制記憶體分配,並指定正確長度的位址。 這表示 MFC 一律可以告訴 DAO「何處」放置數據,從而允許直接系結至成員變數。 系結結構的其餘部分會填入記憶體配置回呼函式的位址,以及數據行系結的類型(依數據行名稱系結)。BindParam這是簡單的作業,會使用參數成員中指定的參數值來呼叫
SetParamValue。Fixup填入每個欄位的 NULL 狀態。
SetFieldNull此作業只會將每個欄位狀態標示為 NULL ,並將成員變數的值設定為 PSEUDO_NULL。
SetDirtyField針對標示為「已變更」的每個欄位呼叫
SetFieldValue。
其餘所有作業僅處理使用資料快取。 數據快取是目前記錄中數據的額外緩衝區,可用來讓某些專案更簡單。 例如,可以自動偵測到「肮髒」字段。 如在線檔中所述,它可以完全關閉或在欄位層級關閉。 緩衝區的實現使用映射。 此映射用於對應動態分配的數據副本與「綁定」字段位址(或 CDaoRecordset 衍生的數據成員)。
AllocCache動態分配快取的字段值,並將其新增至映射。
FreeCache刪除快取的域值,並將它從地圖中移除。
StoreField將目前的域值複製到數據快取中。
LoadField將快取的值複製到欄位變數。
MarkForAddNew檢查目前的欄位值是否為非 NULL ,並視需要將其標示為已變更。
MarkForEdit比較目前的欄位值與資料快取,並在必要時標記為髒資料。
小提示
在標準數據類型的現有 DFX 例程上建立自定義 DFX 例程的模型。