次の方法で共有


TN053: DAO データベース クラス用のカスタム DFX ルーチン

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 レコード フィールド交換メカニズム (DFX) は、 CDaoRecordset クラスを使用する場合のデータの取得と更新の手順を簡略化するために使用されます。 このプロセスは、 CDaoRecordset クラスのデータ メンバーを使用して簡略化されます。 CDaoRecordsetから派生することで、テーブルまたはクエリの各フィールドを表す派生クラスにデータ メンバーを追加できます。 この "静的バインディング" メカニズムは単純ですが、すべてのアプリケーションで選択できるデータ フェッチ/更新方法ではない可能性があります。 DFX は、現在のレコードが変更されるたびに、バインドされたすべてのフィールドを取得します。 通貨が変更されたときにすべてのフィールドをフェッチする必要のないパフォーマンス重視のアプリケーションを開発している場合は、 CDaoRecordset::GetFieldValueCDaoRecordset::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 ルーチンをモデル化します。

こちらも参照ください

番号別テクニカル ノート
カテゴリ別テクニカル ノート