テクニカル ノート 43: RFX ルーチン

Note

次のテクニカル ノートは、最初にオンライン ドキュメントの一部とされてから更新されていません。 結果として、一部のプロシージャおよびトピックが最新でないか、不正になります。 最新の情報について、オンライン ドキュメントのキーワードで関係のあるトピックを検索することをお勧めします。

このメモでは、レコード フィールドエクスチェンジ (RFX) アーキテクチャについて説明します。 また、RFX_ プロシージャを記述する方法について説明します。

レコード フィールドエクスチェンジ の概要

すべてのレコードセット フィールド関数は、C++ コードを使用して行われます。 特別なリソースやマジック マクロはありません。 メカニズムの中心は、すべての派生レコードセット クラスでオーバーライドする必要がある仮想関数です。 これは常に次の形式で見つかります。

void CMySet::DoFieldExchange(CFieldExchange* pFX)
{
    //{{AFX_FIELD_MAP(CMySet)
        <recordset exchange field type call>
        <recordset exchange function call>
    //}}AFX_FIELD_MAP
}

特殊な形式の AFX コメントを使用すると、ClassWizard がこの関数内のコードを見つけて編集できます。 ClassWizard と互換性がないコードは、特殊な形式のコメントの外部に配置する必要があります。

上の例では、<recordset_exchange_field_type_call> 形式です:

pFX->SetFieldType(CFieldExchange::outputColumn);

および <recordset_exchange_function_call> 形式です:

RFX_Custom(pFX, "Col2", m_Col2);

ほとんどの RFX_ 関数は上に示すように 3 つの引数がありますが、一部 (RFX_TextRFX_Binary など) には追加の省略可能な引数があります。

DoDataExchange 関数には RFX_ 複数の関数が含まれる場合 があります。

MFC で提供されるレコードセット フィールド エクスチェンジ ルーチンの一覧については、「afxdb.h」を参照してください。

レコードセット フィールド呼び出しは、CMySet クラスのフィールド データを格納するメモリ位置 (通常はデータ メンバー) を登録する方法です。

メモ

レコードセット フィールド関数は、CRecordset クラスでのみ動作するように設計されています。 一般に、他の MFC クラスでは使用できません。

データの初期値は、標準の C++ コンストラクター内 (通常は、//{{AFX_FIELD_INIT(CMylSet)//}}AFX_FIELD_INIT コメントのブロック内) に設定します。

RFX_ は、フィールドのダーティ ステータスの返しから、フィールドの編集の準備としてフィールドをアーカイブする操作まで、さまざまな操作をサポートする必要があります。

DoFieldExchange を呼び出す各関数 (SetFieldNullIsFieldDirty など) は、DoFieldExchange の呼び出しを中心に独自の初期化を行います。

しくみ

レコード フィールド エクスチェンジを使用するのに、次を理解する必要はありません。 ただし、これがバックグラウンドでどのように動作しているかを理解すると、実際のエクスチェンジ プロシージャを記述する際に役立ちます。

DoFieldExchange メンバー関数は、Serialize メンバー関数によく似ています。外部フォーム (この場合は ODBC クエリ毛かからの列) とクラスのメンバー データとの間でデータを取得または設定します。 pFX パラメーターは、データ エクスチェンジを行うためのコンテキストであり、CObject::Serialize に対する CArchive パラメーターと似ています。 pFX (CFieldExchange オブジェクト) には、CArchive 方向フラグの一般化に似た操作インジケーターがあります。 RFX 関数は、次の操作をサポートする必要がある場合があります:

  • BindParam — ODBC がパラメーター データを取得する場所を示します。

  • BindFieldToColumn — ODBC が outputColumn データを取得/保存する必要がある場所を示します。

  • Fixup - CString/CByteArray 長さを設定し、NULL 状態ビットを設定します。

  • MarkForAddNew — AddNew 呼び出し以降に値が変更された場合にダーティマークを付けます。

  • MarkForUpdate — 編集呼び出し以降に値が変更された場合にダーティマークを付けます。

  • Name — ダーティとマークされたフィールドのフィールド名を追加します。

  • NameValue — ダーティとマークされたフィールドに "<column name>=" を追加します。

  • Value — "" の後に区切り記号 (',' や ' ' など) を追加します。

  • SetFieldDirty — ステータス ビット ダーティ (つまり変更済み) フィールドを設定します。

  • SetFieldNull — フィールドの null 値を示す状態ビットを設定します。

  • IsFieldDirty — ダーティ ステータス ビットの値を返します。

  • IsFieldNull — Null ステータス ビットの値を返します。

  • IsFieldNullable — フィールドに NULL 値を保持できる場合は TRUE を返します。

  • StoreField — アーカイブ フィールドの値

  • LoadField — アーカイブ フィールドの値を再度読み込みます。

  • GetFieldInfoValue — フィールドに関する一般的な情報を返します。

  • GetFieldInfoOrdinal — フィールドに関する一般的な情報を返します。

ユーザー拡張機能

既定の RFX メカニズムを拡張する方法はいくつかあります。 できます

  • 新しいデータ型を追加します。 次に例を示します。

    CBookmark
    
  • 新しいエクスチェンジ プロシージャ (RFX_) を追加します。

    void AFXAPI RFX_Bigint(CFieldExchange* pFX,
        const char *szName,
        BIGINT& value);
    
  • DoFieldExchange メンバー関数に、追加の RFX 呼び出しまたは他の有効な C++ ステートメントを条件付きで含めてください。

    while (posExtraFields != NULL)
    {
        RFX_Text(pFX,
        m_listName.GetNext(posExtraFields),
        m_listValue.GetNext(posExtraValues));
    }
    

Note

このようなコードは ClassWizard で編集することはできません。また、特殊な形式のコメントの外部でのみ使用する必要があります。

カスタム RFX の書き込み

独自のカスタム RFX 関数を記述するには、既存の RFX 関数をコピーし、独自の目的に変更してください。 コピーする適切な RFX を選択すると、ジョブがはるかに簡単になります。 一部の RFX 関数には、コピーするプロパティを決定するときに考慮しなければならないプロパティがあります。

RFX_LongRFX_Int: これらは最も単純な RFX 関数です。 データ値には特別な解釈は必要ではなく、データ サイズは固定されています。

RFX_Single および RFX_Double: 上記 RFX_Long および RFX_Int 同様に、これらの関数は単純であり、既定の実装を広範囲に利用できます。 ただし、明示的に参照されている場合にのみランタイム浮動小数点ライブラリの読み込みを有効にするには、dbrfx.cpp ではなく dbflt.cpp に格納されます。

RFX_TextRFX_Binary: これら 2 つの関数は、文字列/バイナリ情報を保持するために静的バッファーを事前に割り当て、> を登録するのではなく、これらのバッファーを ODBC SQLBindCol に登録する必要があります。 この理由から、これら 2 つの関数には特殊なコードが多数含まれています。

RFX_Date: ODBC は、自身の TIMESTAMP_STRUCT データ構造に日付けと時刻の情報を返します。 この関数は、日付時刻データを送受信する "プロキシ" として TIMESTAMP_STRUCT を動的に割り当てます。 さまざまな操作では、C++ CTime オブジェクトと TIMESTAMP_STRUCT プロキシの間で日付と時刻の情報を転送しなければなりません。 これにより、この関数はかなり複雑になりますが、データ転送にプロキシを使用する方法の良い例です。

RFX_LongBinary: これは、データの受信と送信に列バインドを使用しない唯一のクラス ライブラリ RFX 関数です。 この関数は BindFieldToColumn 操作を無視し、代わりに修正操作中に、受信する SQL_LONGVARCHAR または SQL_LONGVARBINARY のデータを保持するストレージを割り当て、SQLGetData 呼び出しを実行して割り当てられたストレージに値を取得します。 データ値をデータ ソース (NameValue や Value 操作など) に送り返す準備をする場合、この関数は ODBC の DATA_AT_EXEC 機能を使用します。 SQL_LONGVARBINARY およ びSQL_LONGVARCHARs を使用した動作に関する詳細については、 テクニカル ノート 45 を参照してください。

独自の RFX_ 関数を記述する場合、 CFieldExchange::Default を使用して特定の操作を実装できます。 問題の操作については、既定 の実装を参照してください。 自身の RFX_ 関数で記述する操作が実行される場合、CFieldExchange::Default に委任することができます。 dbrfx.cpp で CFieldExchange::Default を呼び出す例を確認できます

RFX 関数の最初に IsFieldType を呼び出し、FALSE を返す場合は直ちに返すことが重要です。 このメカニズムは、outputColumn に対してパラメーター操作が実行されるのを維持し、その逆 (outputColumn での BindParam の呼び出しなど) を保持します。 さらに、IsFieldTypeoutputColumns (m_nFields) と params (m_nParams) の数を自動的に追跡します。

関連項目

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