TN053:DAO 資料庫類別的自訂 DFX 常式
注意
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) 可用來簡化使用 CDaoRecordset
類別時擷取和更新數據的程式。 使用類別的數據成員 CDaoRecordset
來簡化此程式。 藉由衍生自 CDaoRecordset
,您可以將數據成員加入衍生類別,代表數據表或查詢中的每個字段。 這個「靜態系結」機制很簡單,但可能不是所有應用程式選擇的數據擷取/更新方法。 每次變更當前記錄時,DFX 會擷取每個系結字段。 如果您要開發效能敏感的應用程式,在變更貨幣時不需要擷取每個欄位,則透過 「動態系結」CDaoRecordset::GetFieldValue
CDaoRecordset::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
DAO_WCHAR)。 此外,也會設定所使用的系結類型。 在先前的章節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 例程的模型。