レコードセット: バルク行フェッチ (ODBC)

このトピックの内容は、MFC ODBC クラスに該当します。

クラス CRecordset は、バルク行フェッチをサポートしています。つまり、データ ソースから一度に 1 レコードを取得するのではなく、1 回のフェッチで複数のレコードを一度に取得することができます。 バルク行フェッチを実装できるのは、派生した CRecordset クラスのみです。 データ ソースからレコードセット オブジェクトにデータを転送する処理は、バルク レコード フィールド エクスチェンジ (バルク RFX) と呼ばれます。 CRecordset 派生クラスでバルク行フェッチを使っていない場合、データはレコード フィールド エクスチェンジ (RFX) を介して転送されることに注意してください。 詳細については、「レコード フィールド エクスチェンジ (RFX)」を参照してください。

このトピックでは、次の内容について説明します。

CRecordset がバルク行フェッチをサポートする方法

レコードセット オブジェクトを開く前に、SetRowsetSize メンバー関数を使って行セット サイズを定義することができます。 行セット サイズには、1 回のフェッチで取得すべきレコード数を指定します。 バルク行フェッチが実装されている場合、既定の行セット サイズは 25 です。 バルク行フェッチが実装されていない場合、行セット サイズは 1 に固定されたままになります。

行セット サイズを初期化した後、Open メンバー関数を呼び出します。 バルク行フェッチを実装するには、ここで dwOptions パラメーターの CRecordset::useMultiRowFetch オプションを指定する必要があります。 さらに CRecordset::userAllocMultiRowBuffers オプションを設定できます。 バルク レコード フィールド エクスチェンジ メカニズムでは、フェッチ時に取得された複数行のデータを格納するために配列を使います。 これらのストレージ バッファーは、フレームワークによって自動的に割り当てるか、手動で割り当てることができます。 CRecordset::userAllocMultiRowBuffers オプションを指定すると、割り当てを実行することになります。

次の表は、バルク行フェッチをサポートするために CRecordset に用意されているメンバー関数の一覧です。

メンバー関数 説明
CheckRowsetError フェッチ時に発生したエラーを処理する仮想関数。
DoBulkFieldExchange バルク レコード フィールド エクスチェンジを実装します。 データ ソースからレコードセット オブジェクトに複数行のデータを転送するために自動的に呼び出されます。
GetRowsetSize 行セット サイズに関する現在の設定を取得します。
GetRowsFetched 特定のフェッチ後に実際に取得された行数がわかります。 不完全な行セットがフェッチされた場合を除き、ほとんどの場合、これは行セット サイズです。
GetRowStatus 行セット内の特定の行のフェッチ状態を返します。
RefreshRowset 行セット内の特定の行のデータと状態を更新します。
SetRowsetCursorPosition カーソルを行セット内の特定の行に移動します。
SetRowsetSize 行セット サイズの設定を、指定した値に変更する仮想関数。

特別な考慮事項

バルク行フェッチによってパフォーマンスは向上しますが、機能によっては動作が異なります。 バルク行フェッチの実装を決定する前に、次の点を検討してください。

  • フレームワークによって、自動的に DoBulkFieldExchange メンバー関数が呼び出され、データ ソースからレコードセット オブジェクトにデータが転送されます。 ただし、データはレコードセットからデータ ソースに戻されません。 AddNewEditDelete、または Update メンバー関数を呼び出すと、アサーションに失敗します。 現在、CRecordset にはデータ行を一括して更新するメカニズムが用意されていませんが、ODBC API 関数 SQLSetPos を使って、独自の関数を記述することができます。 SQLSetPos の詳細については、ODBC プログラマーズ リファレンスを参照してください。

  • メンバー関数 IsDeletedIsFieldDirtyIsFieldNullIsFieldNullableSetFieldDirtySetFieldNull は、バルク行フェッチを実装しているレコードセットに対して使用できません。 ただし、IsDeleted ではなく GetRowStatus を、IsFieldNullable ではなく GetODBCFieldInfo を呼び出すことはできます。

  • Move 操作により、レコードセットは行セット単位で再配置されます。 たとえば、最初の行セット サイズが 10 で、レコード数が 100 であるレコードセットを開くとします。 Open では、行 1 から 10 をフェッチします。現在のレコードは行 1 に配置されます。 MoveNext を呼び出すと、次の行ではなく、次の行セットがフェッチされます。 この行セットは行 11 から 20 で構成され、現在のレコードは 11 行目に配置されています。 バルク行フェッチが実装されている場合、MoveNextMove( 1 ) は同等ではないことに注意してください。 Move( 1 ) では、現在のレコードの 1 行目から始まる行セットをフェッチします。 この例では、Open を呼び出した後に Move( 1 ) を呼び出すと、現在のレコードが 2 行目に配置された、行 2 から 11 で構成される行セットがフェッチされます。 詳細については、Move メンバー関数を参照してください。

  • レコード フィールド エクスチェンジとは異なり、ウィザードはバルク レコード フィールド エクスチェンジをサポートしていません。 つまり、フィールド データ メンバーを手動で宣言し、バルク RFX 関数の呼び出しを記述して DoBulkFieldExchange を手動でオーバーライドする必要があります。 詳細については、クラス ライブラリ リファレンスレコード フィールド エクスチェンジ関数に関するページを参照してください。

バルク レコード フィールド エクスチェンジを実装する方法

バルク レコード フィールド エクスチェンジを使って、データ ソースからレコードセット オブジェクトにデータの行セットを転送します。 バルク RFX 関数には、このデータを格納するための配列と、行セット内の各データ項目の長さを格納するための配列を使います。 クラス定義では、データの配列にアクセスするためのポインターとして、フィールド データ メンバーを定義する必要があります。 さらに、長さの配列にアクセスするポインターのセットを定義する必要があります。 パラメーター データ メンバーは、ポインターとして宣言しないでください。バルク レコード フィールド エクスチェンジを使うときにパラメーター データ メンバーを宣言することは、レコード フィールド エクスチェンジを使うときに宣言することと同じです。 次のコードは、簡単な例を示しています。

class MultiRowSet : public CRecordset
{
public:
   // Field/Param Data
      // field data members
      long* m_rgID;
      LPSTR m_rgName;

      // pointers for the lengths
      // of the field data
      long* m_rgIDLengths;
      long* m_rgNameLengths;

      // input parameter data member
      CString m_strNameParam;

   .
   .
   .
}

これらのストレージ バッファーは、手動で割り当てるか、フレームワークで自動的に割り当てることができます。 バッファーを自分で割り当てるには、dwOptions パラメーターの CRecordset::userAllocMultiRowBuffers オプションを Open メンバー関数で指定する必要があります。 配列のサイズは、少なくとも行セット サイズと同じに設定してください。 フレームワークで自動的に割り当てる場合は、ポインターを NULL に初期化する必要があります。 通常、これはレコードセット オブジェクトのコンストラクターで行われます。

MultiRowSet::MultiRowSet( CDatabase* pDB )
   : CRecordset( pDB )
{
   m_rgID = NULL;
   m_rgName = NULL;
   m_rgIDLengths = NULL;
   m_rgNameLengths = NULL;
   m_strNameParam = "";

   m_nFields = 2;
   m_nParams = 1;

   .
   .
   .
}

最後に、DoBulkFieldExchange メンバー関数をオーバーライドする必要があります。 フィールド データ メンバーの場合は、バルク RFX 関数を呼び出します。任意のパラメーター データ メンバーの場合は、RFX 関数を呼び出します。 Open に SQL ステートメントまたはストアド プロシージャを渡してレコードセットを開いた場合、バルク RFX 呼び出しを行う順序は、レコードセット内の列の順序に対応している必要があります。同様に、パラメーターに対する RFX 呼び出しの順序は、SQL ステートメントまたはストアド プロシージャ内のパラメーターの順序に対応している必要があります。

void MultiRowSet::DoBulkFieldExchange( CFieldExchange* pFX )
{
   // call the Bulk RFX functions
   // for field data members
   pFX->SetFieldType( CFieldExchange::outputColumn );
   RFX_Long_Bulk( pFX, _T( "[colRecID]" ),
                  &m_rgID, &m_rgIDLengths );
   RFX_Text_Bulk( pFX, _T( "[colName]" ),
                  &m_rgName, &m_rgNameLengths, 30 );

   // call the RFX functions for
   // for parameter data members
   pFX->SetFieldType( CFieldExchange::inputParam );
   RFX_Text( pFX, "NameParam", m_strNameParam );
}

Note

派生 CRecordset クラスがスコープ外に出る前に、Close メンバー関数を呼び出す必要があります。 こうすることで、フレームワークによって割り当てられたすべてのメモリを解放できます。 バルク行フェッチを実装したかどうかに関係なく、プログラミングの習慣として、常に明示的に Close を呼び出すことをお勧めします。

レコード フィールド エクスチェンジ (RFX) の詳細については、「レコード フィールド エクスチェンジ: RFX の動作のしくみ」を参照してください。 パラメーターの使用の詳細については、「CFieldExchange::SetFieldType」と「レコードセット: パラメーターを利用したレコードセット (ODBC)」を参照してください。

関連項目

レコードセット (ODBC)
CRecordset::m_nFields
CRecordset::m_nParams