レコード フィールド エクスチェンジ: RFX の動作のしくみ
このトピックでは、RFX プロセスについて説明します。 これは以下を含む高度なトピックです。
Note
このトピックの内容は、バルク行フェッチが実装されていない CRecordset
から派生したクラスを対象にしています。 バルク行フェッチを使用している場合は、バルク レコード フィールド エクスチェンジ (Bulk RFX) が実装されます。 Bulk RFX は、RFX に似ています。 違いを理解するには、「レコードセット: バルク行フェッチ (ODBC)」を参照してください。
RFX とレコードセット
レコードセット オブジェクトのフィールド データ メンバーは、組み合わせて、1 つのレコードの選択した列を保持する編集バッファーを構成します。 レコードセットが最初に開かれ、最初のレコードを読み取ろうとするときに、RFX では、選択した各列を適切なフィールド データ メンバーのアドレスにバインドします (関連付けます)。 レコードセットがレコードを更新すると、RFX によって ODBC API 関数が呼び出され、SQL UPDATE または INSERT ステートメントがドライバーに送信されます。 RFX では、フィールド データ メンバーに関する知識を使って、書き込む列を指定します。
フレームワークは、必要に応じてそのコンテンツを復元できるように、特定の段階で編集バッファーをバックアップします。 RFX では、新しいレコードを追加する前、および既存のレコードを編集する前に、編集バッファーをバックアップします。 場合によっては (たとえば AddNew
の後に続く Update
の呼び出しなど)、編集バッファーを復元します。 たとえば Update
を呼び出す前に別のレコードに移動するなどして、新しく変更された編集バッファーを破棄した場合、編集バッファーは復元されません。
RFX では、データ ソースとレコードセットのフィールド データ メンバーの間でデータを交換するだけでなく、バインド パラメーターも管理されます。 レコードセットが開かれると、すべてのパラメーター データ メンバーは、CRecordset::Open
によって構築される SQL ステートメント内の "?" プレースホルダーの順序でバインドされます。 詳細については、「レコードセット: パラメーターを利用したレコードセット (ODBC)」を参照してください。
レコードセット クラスの DoFieldExchange
のオーバーライドがすべての処理を行い、双方向にデータを移動させます。 ダイアログ データ エクスチェンジ (DDX) と同様に、RFX にはクラスのデータ メンバーに関する情報が必要です。 ウィザードでは、ウィザードで指定するフィールド データ メンバー名とデータ型に基づいて、レコードセット固有の DoFieldExchange
の実装を作成することによって、必要な情報が提供されます。
レコード フィールド エクスチェンジのプロセス
このセクションでは、レコードセット オブジェクトが開かれたときと、レコードを追加、更新、削除したときの RFX イベントのシーケンスについて説明します。 このトピックに含まれる表「レコードセットを開くときの RFX 操作のシーケンス」と表「スクロール中の RFX 操作のシーケンス」では、RFX によってレコードセットの Move
コマンドが処理されるときと、RFX によって更新が管理されるときのプロセスが示されています。 これらのプロセス中に DoFieldExchange が呼び出され、さまざまな操作が実行されます。 CFieldExchange オブジェクトの m_nOperation
データ メンバーによって、要求されている操作が決定されます。 この内容を読む前に、「レコードセット: レコード選択のしくみ (ODBC)」と「レコードセット: レコード更新のしくみ (ODBC)」を読んでおくと役立つかもしれません。
RFX: 列とパラメーターの初期バインド
レコードセット オブジェクトの Open メンバー関数を呼び出すと、次の RFX アクティビティが、示されている順序で発生します。
レコードセットにパラメーター データ メンバーが含まれている場合、フレームワークは
DoFieldExchange
を呼び出し、レコードセットの SQL ステートメント文字列内のパラメーター プレースホルダーにパラメーターをバインドします。 SELECT ステートメント内で見つかった各プレースホルダーに対して、パラメーターの値のデータ型に依存する表現が使用されます。 これは、SQL ステートメントの準備ができてから実行されるまでの間に発生します。 ステートメントの準備の詳細については、「ODBC のプログラマ リファレンス」の::SQLPrepare
関数を参照してください。フレームワークは、もう一度
DoFieldExchange
を呼び出して、選択した列の値をレコードセット内の対応するフィールド データ メンバーにバインドします。 これにより、レコードセット オブジェクトが、最初のレコードの列を含む編集バッファーとして設定されます。レコードセットは SQL ステートメントを実行し、データ ソースは最初のレコードを選択します。 レコードの列は、レコードセットのフィールド データ メンバーに読み込まれます。
次の表に、レコードセットを開くときの RFX 操作のシーケンスを示します。
レコードセットを開くときの RFX 操作のシーケンス
操作 | DoFieldExchange の操作 | データベースまたは SQL の操作 |
---|---|---|
1. レコードセットを開きます。 | ||
2. SQL ステートメントを構築します。 | ||
3. SQL を送信します。 | ||
4. パラメーター データ メンバーをバインドします。 | ||
5. フィールド データ メンバーを列にバインドします。 | ||
6. ODBC によって移動が行われ、データが入力されます。 | ||
7. C++ のデータを修正します。 |
レコードセットでは、ODBC の準備実行を使用して、同じ SQL ステートメントを使った高速の再クエリを実現します。 準備実行の詳細については、「ODBC のプログラマ リファレンス」を参照してください。
RFX: スクロール
あるレコードから別のレコードにスクロールすると、フレームワークによって DoFieldExchange
が呼び出され、以前にフィールド データ メンバーに格納されていた値が新しいレコードの値に置き換えられます。
次の表は、ユーザーがレコード間を移動するときの RFX 操作のシーケンスを示しています。
スクロール中の RFX 操作のシーケンス
操作 | DoFieldExchange の操作 | データベースまたは SQL の操作 |
---|---|---|
1. MoveNext またはその他の Move 関数のいずれかを呼び出します。 |
||
2. ODBC によって移動が行われ、データが入力されます。 | ||
3. C++ のデータを修正します。 |
RFX: 新しいレコードの追加と既存のレコードの編集
新しいレコードを追加する場合、レコードセットは、新しいレコードの内容を構築するための編集バッファーとして機能します。 レコードを追加する場合と同様に、レコードを編集するには、レコードセットのフィールド データ メンバーの値を変更する必要があります。 RFX の観点からは、シーケンスは次のようになります。
ユーザーがレコードセットの AddNew または Edit メンバー関数を呼び出すと、RFX では、後で復元できるように現在の編集バッファーが格納されます。
AddNew
またはEdit
により編集バッファーのフィールドの準備が行われ、RFX で変更されたフィールド データ メンバーを検出できるようになります。新しいレコードには新しい値を比較するための以前の値がないため、
AddNew
では各フィールド データ メンバーの値が PSEUDO_NULL 値に設定されます。 その後、Update
を呼び出すと、RFX では各データ メンバーの値が PSEUDO_NULL 値と比較されます。 違いがある場合、データ メンバーは設定されています。 (PSEUDO_NULL は、本物の Null 値を持つレコード列と同じではなく、C++ の NULL と同じでもありません。)AddNew
のUpdate
呼び出しとは異なり、Edit
のUpdate
呼び出しでは、更新された値を、PSEUDO_NULL を使用するのではなく、以前に格納された値を比較します。 その違いは、AddNew
には比較のために以前に格納された値がないことです。値を編集する必要がある、または新しいレコードに入力したいフィールド データ メンバーの値を直接設定します。 これには、
SetFieldNull
の呼び出しが含まれる場合があります。Update を呼び出すと、ステップ 2 で説明されているように、変更されたフィールド データ メンバーがチェックされます (表「スクロール中の RFX 操作のシーケンス」を参照)。 何も変更されていない場合、
Update
は 0 を返します。 一部のフィールド データ メンバーが変更されている場合、Update
によってレコード内のすべての更新されたフィールドの値を含む SQL INSERT ステートメントが準備され、実行されます。AddNew
の場合、Update
は最後に、AddNew
呼び出しの前に最新だった、レコードの以前に格納されていた値を復元します。Edit
の場合、新しい編集された値はそのまま残ります。
次の表は、新しいレコードを追加したり、既存のレコードを編集したりするときの RFX 操作のシーケンスを示しています。
AddNew および Edit 中の RFX 操作のシーケンス
操作 | DoFieldExchange の操作 | データベースまたは SQL の操作 |
---|---|---|
1. AddNew または Edit を呼び出します。 |
||
2. 編集バッファーをバックアップします。 | ||
3. AddNew の場合は、フィールド データ メンバーを "クリーン" および Null としてマークします。 |
||
4. レコードセットのフィールド データ メンバーに値を代入します。 | ||
5. Update を呼び出します。 |
||
6. 変更されたフィールドをチェックします。 | ||
7. AddNew の場合は SQL INSERT ステートメントを、Edit の場合は UPDATE ステートメントを構築します。 |
||
8. SQL を送信します。 | ||
9. AddNew の場合は、編集バッファーをバックアップ済みの内容に復元します。 Edit の場合は、バックアップを削除します。 |
RFX: 既存のレコードの削除
レコードを削除すると、RFX では、レコードが削除されたことを示すためにすべてのフィールドが NULL に設定され、そのレコードから移動する必要があります。 その他の RFX シーケンス情報は必要ありません。
関連項目
レコード フィールド エクスチェンジ (RFX)
MFC ODBC コンシューマー
マクロ、グローバル関数、およびグローバル変数
CFieldExchange クラス
CRecordset::DoFieldExchange