注
DAO は Access データベースで使用され、Office 2013 でサポートされています。 DAO 3.6 は最終バージョンであり、古いと見なされます。 Visual C++ 環境とウィザードは DAO をサポートしていません (ただし、DAO クラスは含まれており、引き続き使用できます)。 新しいプロジェクトには 、OLE DB テンプレート または ODBC および MFC を使用することをお勧めします。 DAO は、既存のアプリケーションの保守にのみ使用する必要があります。
このテクニカル ノートでは、DAO レコード フィールド交換 (DFX) メカニズムについて説明します。 DFX ルーチンで何が起こっているかを理解するために、 DFX_Text
関数を例として詳しく説明します。 このテクニカル ノートの追加の情報ソースとして、他の個々の DFX 関数のコードを調べることができます。 カスタム RFX ルーチン (ODBC データベース クラスで使用) が必要になる場合ほど、カスタム DFX ルーチンは必要ありません。
このテクニカル ノートには、次のものが含まれています。
DFX の概要
DAO レコード フィールド Exchange と動的バインディングの使用例
DFX の概要
DAO レコード フィールド交換メカニズム (DFX) は、 CDaoRecordset
クラスを使用する場合のデータの取得と更新の手順を簡略化するために使用されます。 このプロセスは、 CDaoRecordset
クラスのデータ メンバーを使用して簡略化されます。
CDaoRecordset
から派生することで、テーブルまたはクエリの各フィールドを表す派生クラスにデータ メンバーを追加できます。 この "静的バインディング" メカニズムは単純ですが、すべてのアプリケーションで選択できるデータ フェッチ/更新方法ではない可能性があります。 DFX は、現在のレコードが変更されるたびに、バインドされたすべてのフィールドを取得します。 通貨が変更されたときにすべてのフィールドをフェッチする必要のないパフォーマンス重視のアプリケーションを開発している場合は、 CDaoRecordset::GetFieldValue
と CDaoRecordset::SetFieldValue
を介した "動的バインディング" が、選択したデータ アクセス方法である可能性があります。
注
DFX と動的バインディングは相互に排他的ではないため、静的バインディングと動的バインディングのハイブリッド使用を使用できます。
例 1 - DAO レコード フィールド Exchange のみを使用する
( 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 レコード フィールド Exchange と動的バインディングの使用
( 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 関数への呼び出しをディスパッチします。 内部 MFC 関数 DoFieldExchange
呼び出す前に、操作の種類を設定します。 次の一覧は、さまざまな操作の種類と簡単な説明を示しています。
オペレーション | 説明 |
---|---|
AddToParameterList |
PARAMETERS 句をビルドする |
AddToSelectList |
SELECT 句をビルドする |
BindField |
バインド構造を設定する |
BindParam |
パラメーター値を設定します |
Fixup |
NULL 状態を設定します |
AllocCache |
ダーティ チェック用にキャッシュを割り当てます |
StoreField |
現在のレコードをキャッシュに保存します |
LoadField |
キャッシュをメンバー値に復元します |
FreeCache |
キャッシュを解放します |
SetFieldNull |
フィールドの状態と値を NULL に設定します |
MarkForAddNew |
PSEUDO NULL でない場合は、フィールドをダーティにマークします |
MarkForEdit |
キャッシュと一致しない場合は、フィールドをダーティにマークします |
SetDirtyField |
ダーティとしてマークされたフィールド値を設定します |
次のセクションでは、各操作について、 DFX_Text
について詳しく説明します。
DAO レコード フィールド交換プロセスについて理解する最も重要な機能は、CDaoRecordset
オブジェクトのGetRows
関数を使用することです。 DAO GetRows
関数は、いくつかの方法で機能します。 このテクニカル ノートでは、このテクニカル ノートの範囲外であるため、 GetRows
について簡単に説明します。
DAO GetRows
は、いくつかの方法で動作します。
一度に複数のレコードと複数のデータ フィールドをフェッチできます。 これにより、大きなデータ構造と、各フィールドへの適切なオフセット、および構造内のデータの各レコードに対する適切なオフセットを処理する複雑さにより、データ アクセスを高速化できます。 MFC では、この複数レコード フェッチ メカニズムは利用されません。
GetRows
機能するもう 1 つの方法は、プログラマがデータの 1 つのレコードに対して各フィールドの取得されたデータのバインド アドレスを指定できるようにすることです。DAO は、呼び出し元がメモリを割り当てることができるように、可変長列の呼び出し元にも "コールバック" します。 この 2 つ目の機能には、データのコピー数を最小限に抑えるだけでなく、クラス (
CDaoRecordset
派生クラス) のメンバーにデータを直接格納できるという利点があります。 この 2 つ目のメカニズムは、MFC が派生クラスのデータ メンバーにバインドするために使用CDaoRecordset
メソッドです。
カスタム DFX ルーチンの機能
この説明から、DFX 関数で実装される最も重要な操作は、 GetRows
を正常に呼び出すために必要なデータ構造を設定する機能である必要があります。 DFX 関数でもサポートする必要がある他の操作がいくつかありますが、 GetRows
呼び出しを正しく準備するほど重要でも複雑でもありません。
DFX の使用については、オンライン ドキュメントで説明されています。 基本的に、2 つの要件があります。 まず、バインドされた各フィールドとパラメーターの 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 ルーチンをモデル化します。