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

更新 : 2007 年 11 月

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

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

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

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

  • バルク行フェッチを使用する場合の注意事項

  • バルク レコード フィールド エクスチェンジ (Bulk RFX: Bulk Record Field Exchange) の実装方法

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

レコードセット オブジェクトを開く前に、行セットのサイズを SetRowsetSize メンバ関数で定義できます。行セットのサイズは、一度のフェッチで取得するレコード数を指します。バルク行フェッチが実装されている場合、既定の行セットのサイズは 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 の詳細については、MSDN ドキュメントの『ODBC SDK Programmer's Reference』を参照してください。

  • IsDeletedIsFieldDirtyIsFieldNullIsFieldNullableSetFieldDirty、および SetFieldNull の各メンバ関数は、バルク行フェッチを実装しているレコードセットでは使用できません。ただし、IsDeleted の代わりに GetRowStatus を、IsFieldNullable の代わりに GetODBCFieldInfo を呼び出すことができます。

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

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

バルク レコード フィールド エクスチェンジ (Bulk RFX: Bulk Record Field Exchange) の実装方法

バルク レコード フィールド エクスチェンジは、データ ソースからレコードセット オブジェクトにデータの行セットを転送します。Bulk 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;

   .
   .
   .
}

配列の格納バッファは、フレームワークによって自動的に割り当てることも、手動で割り当てることもできます。手動で割り当てるには、Open メンバ関数で dwOptions パラメータの CRecordset::userAllocMultiRowBuffers オプションを指定します。配列のサイズは、行セットのサイズ以上とします。フレームワークによって自動的に配列を割り当てるには、ポインタを 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 メンバ関数をオーバーライドします。フィールド データ メンバに対しては Bulk RFX 関数を呼び出し、パラメータ データ メンバに対しては RFX 関数を呼び出します。SQL ステートメントまたはストアド プロシージャを Open に渡してレコードセットを開いた場合は、レコードセットの列の順序に従って Bulk 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 );
}
77dcbckz.alert_note(ja-jp,VS.90).gifメモ :

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

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

参照

概念

レコードセット (ODBC)

参照

CRecordset::m_nFields

CRecordset::m_nParams