レコード フィールド エクスチェンジ : RFX の動作のしくみ
更新 : 2007 年 11 月
このトピックでは、RFX 処理について説明します。このトピックは上級者向けのトピックです。以下の内容について説明します。
RFX とレコードセット
RFX 処理の内容
メモ : |
---|
このトピックの内容は、バルク行フェッチが実装されていない CRecordset の派生クラスを対象にしています。バルク行フェッチを使用している場合は、バルク レコード フィールド エクスチェンジ (Bulk RFX: Bulk Record Field Exchange) が実装されています。Bulk RFX と RFX は似ています。両者の差異については、「レコードセット : バルク行フェッチ (ODBC)」を参照してください。 |
RFX とレコードセット
レコードセット オブジェクトのフィールド データ メンバは、全体で 1 つの編集バッファを設け、そこに 1 つのレコードの選択されている列を格納します。レコードセットを初めて開き、先頭のレコードを読み込むときに、選択された各列が該当するフィールド データ メンバのアドレスに結び付けられます。レコードセットによってレコードが更新されると、RFX は、ODBC API 関数を呼び出して、SQL の UPDATE ステートメントまたは INSERT ステートメントをドライバに送出します。RFX は、フィールド データ メンバの情報に基づき、書き込む列を決定します。
フレームワークは、特定のタイミングでエディット バッファをバックアップして、必要に応じて内容を復元できるように保存します。RFX は、新しいレコードを追加する前および既存のレコードを編集する前に、エディット バッファをバックアップします。エディット バッファにバックアップした内容を復元するのは、AddNew の後に Update を呼び出すときなどです。更新したエディット バッファを捨てたくないときに、Update を呼び出す前に他のレコードに移動するなどして、エディット バッファの変更内容を破棄した場合は、エディット バッファは復元されません。
データ ソースとレコードセット フィールド データ メンバ間のデータ交換のほか、RFX はパラメータの管理も行います。レコードセットを開くと、すべてのパラメータ データ メンバは、CRecordset::Open で構築される SQL ステートメントの "?" プレースホルダの順に結び付けられます。詳細については、「レコードセット : パラメータを利用したレコードセット (ODBC)」を参照してください。
レコードセット クラスのオーバーライド関数 DoFieldExchange は、データの双方向転送におけるあらゆる処理を行います。RFX は、ダイアログ データ エクスチェンジ (DDX: Dialog Data Exchange) と同じように、レコードセット クラスのデータ メンバに関する情報を必要とします。ウィザードは、指定されたフィールド データ メンバ名とデータ型に基づいて、DoFieldExchange のレコードセット固有の実装を作成して、必要な情報を提供します。
レコード フィールド エクスチェンジの処理
ここでは、レコードセット オブジェクトを開くとき、およびレコードを作成、更新、削除するときに発生する RFX イベントの流れについて説明します。レコードセットの Move コマンドを処理する場合および更新処理を行う場合の RFX の動作については、表「レコードセットを開くときの RFX 処理の流れ」および「スクロールを行うときの RFX 処理の流れ」を参照してください。これらの処理では、さまざまな操作を行うために DoFieldExchange が呼び出されます。必要な操作は、CFieldExchange オブジェクトのデータ メンバ m_nOperation によって指定されます。以下の説明を読む前に、基礎知識として、「レコードセット : レコード選択のしくみ (ODBC)」と「レコードセット : レコード更新のしくみ (ODBC)」を参照してください。
RFX : 列とパラメータの初期設定
プログラムからレコードセット オブジェクトのメンバ関数 Open を呼び出すと、以下の RFX の処理がこの順に行われます。
パラメータ データ メンバを持つレコードセットでは、フレームワークは、DoFieldExchange を呼び出して、パラメータをレコードセットの SQL ステートメントの文字列パラメータ プレースホルダに結び付けます。データ型に応じたパラメータ値が、SELECT ステートメントのプレースホルダごとに書き込まれます。この処理は、SQL ステートメントの "作成" 後、実際に実行される前に行われます。SQL ステートメントの作成については、『ODBC Programmer's Reference』の ::SQLPrepare 関数に関するトピックを参照してください。
フレームワークは、DoFieldExchange をもう 1 回呼び出して、選択された列の値を該当するレコードセットのフィールド データ メンバに結び付けます。これにより、レコードセット オブジェクトが、最初のレコードの列を格納したエディット バッファとして設定されます。
レコードセットが SQL ステートメントを実行し、データ ソースが最初のレコードを選択します。レコードの列がレコードセットのフィールド データ メンバに読み込まれます。
次の表に、レコードセットを開くときの RFX 処理の流れを示します。
レコードセットを開くときの RFX 処理の流れ
プログラマの操作 |
DoFieldExchange の処理 |
Database/SQL の動作 |
---|---|---|
1. レコードセットを開きます。 |
|
|
|
2. SQL ステートメントを作成します。 |
|
|
|
3. SQL を送出します。 |
|
4. パラメータ データ メンバをバインドします。 |
|
|
5. フィールド データ メンバを列にバインドします。 |
|
|
|
6. ODBC によって移動、データ転送が行われます。 |
|
7. データを C++ で扱える形式に変換します。 |
|
レコードセットは、ODBC のプリペアド エクゼキューションを使用して、同一の SQL ステートメントによるクエリの再実行を高速化します。プリペアド エクゼキューションの詳細については、MSDN ライブラリの『ODBC Programmer's Reference』を参照してください。
RFX : スクロール
レコードをスクロールすると、フレームワークは、DoFieldExchange を呼び出して、フィールド データ メンバの値を新しいレコードの内容に置き換えます。
次の表に、レコードをスクロールするときの RFX の処理の流れを示します。
スクロールを行うときの RFX 処理の流れ
プログラマの操作 |
DoFieldExchange の処理 |
Database/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 ではなく、以前保存した値と比較します。Edit と AddNew の違いは、AddNew には比較対象になる過去の値が保存されていないという点です。
編集するフィールド データ メンバ、または新しいレコード用に値を設定するフィールド データ メンバの値は、直接設定します。この場合、SetFieldNull を呼び出すことができます。
Update を呼び出すと、フィールド データ メンバが変更されているかどうかが確認されます (手順 2 を参照)。詳細については、表「スクロールを行うときの RFX 処理の流れ」を参照してください。変更がないときは、Update は 0 を返します。フィールド データ メンバが変更されているときは、Update は、変更されたすべてのフィールドの値を更新する SQL INSERT ステートメントを作成し、実行します。
AddNew の場合、Update は、AddNew を呼び出す前に現在のレコードに保存されていた値を復元することによって処理を完了させます。Edit の場合は、新しく編集した結果が残ります。
次の表に、レコードを新規作成または既存レコードを編集したときの RFX 処理の流れを示します。
AddNew および Edit を実行したときの RFX 処理の流れ
プログラマの操作 |
DoFieldExchange の処理 |
Database/SQL の動作 |
---|---|---|
1. AddNew または Edit を呼び出します。 |
|
|
|
2. エディット バッファをバックアップします。 |
|
|
3. AddNew の場合は、フィールド データ メンバを "変更なし (クリーン)" で Null としてマークします。 |
|
4. レコードセットのフィールド データ メンバに値を代入します。 |
|
|
5. Update を呼び出します。 |
|
|
|
6. フィールドが変更されているかどうかをチェックします。 |
|
|
7. SQL INSERT ステートメント (AddNew の場合) または UPDATE ステートメント (Edit の場合) を作成します。 |
|
|
|
8. SQL を送出します。 |
|
9. AddNew では、エディット バッファの内容をバックアップしておいた値に戻します。Edit では、バックアップを消去します。 |
|
RFX : レコードの削除
レコードを削除すると、RFX は、すべてのフィールドに NULL を代入して、削除されたことを記録します。実際の削除処理は、プログラム中で行う必要があります。削除については、これ以外の RFX 処理は必要ありません。