レコードセット: バルク行フェッチ (ODBC)
このトピックの内容は、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 が提供しているメンバー関数の一覧です。
メンバー関数 |
Description |
---|---|
フェッチ中に発生したエラーを処理する仮想関数です。 |
|
バルク レコード フィールド エクスチェンジを実装します。データ ソースからレコードセット オブジェクトに複数行のデータを転送するときに、自動的に呼び出されます。 |
|
行セットのサイズの現在の設定を取得します。 |
|
フェッチで実際に取得された行数を示します。行セットのフェッチが不完全であった場合を除いて、行セットのサイズと同じになります。 |
|
行セット内の特定の行に関するフェッチ ステータスを返します。 |
|
行セット内の特定の行のデータとステータスを更新します。 |
|
行セット内の特定の行にカーソルを移動します。 |
|
行セットのサイズの設定を指定された値に変更する仮想関数です。 |
バルク行フェッチを使用する場合の注意事項
バルク行フェッチを使用すると、パフォーマンスの向上につながる反面、一部の機能が変更されます。バルク行フェッチを実装する前に、以下の事項を確認しておいてください。
フレームワークでは、DoBulkFieldExchange メンバー関数が自動的に呼び出され、データがデータ ソースからレコードセット オブジェクトに転送されます。しかし、レコードセットからデータ ソースには転送されません。AddNew、Edit、Delete、または Update の各メンバー関数を呼び出すと、アサーションは失敗します。CRecordset には、現在複数行のデータを更新する機構はありませんが、ODBC API 関数の SQLSetPos を使用すると、独自の関数を記述できます。SQLSetPos の詳細については、MSDN ドキュメントの『ODBC SDK Programmer's Reference』を参照してください。
IsDeleted、IsFieldDirty、IsFieldNull、IsFieldNullable、SetFieldDirty、および SetFieldNull の各メンバー関数は、バルク行フェッチを実装しているレコードセットでは使用できません。ただし、IsDeleted の代わりに GetRowStatus を、IsFieldNullable の代わりに GetODBCFieldInfo を呼び出すことができます。
Move を呼び出すと、レコードセットは行セット単位で移動します。たとえば、レコードセットに 100 のレコードがあり、このレコードセットの最初の行セット サイズが 10 であるとします。Open を呼び出すと、1 から 10 までの行がフェッチされ、現在のレコードは行 1 になります。ここで MoveNext を呼び出すと、次の行ではなくて次の行セットがフェッチされます。この行セットは 11 から 20 までの行で構成され、現在のレコードは行 11 になります。バルク行フェッチが実装されている場合、MoveNext と Move( 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 );
}
[!メモ]
CRecordset の派生クラスがスコープの外に出る前に、Close メンバー関数を必ず呼び出してください。これは、フレームワークによって割り当てられたメモリを解放するためです。バルク行フェッチを実装しているかどうかにかかわらず、プログラミング上の習慣として、常に Close を明示的に呼び出すことをお勧めします。
レコード フィールド エクスチェンジ (RFX: Record Field Exchange) の詳細については、「レコード フィールド エクスチェンジ : RFX の動作のしくみ」を参照してください。パラメーターの使い方の詳細については、「CFieldExchange::SetFieldType」と「レコードセット : パラメーターを利用したレコードセット (ODBC)」を参照してください。