Поделиться через


Набор записей: пакетная выборка строк (ODBC)

Обновлен: Ноябрь 2007

В этом разделе приведены сведения, относящиеся к классам ODBC библиотеки MFC.

Класс CRecordset обеспечивает поддержку пакетной выборки строк, что подразумевает извлечение из источника данных нескольких (а не одной) записей за одну операцию выборки. Реализовать пакетную выборку строк можно только в классе, производном от CRecordset. Процесс передачи данных из источника данных в объект набора записей называется блочным (или пакетным) обменом полями записей (Bulk RFX). Обратите внимание, что если в производном от CRecordset классе не используется пакетная выборка строк, то данные передаются посредством обмена полей записей (RFX). Дополнительные сведения см. в разделе Обмен полей записей (RFX).

В данном разделе рассматриваются следующие вопросы:

  • Поддержка пакетной выборки строк в классе CRecordset.

  • Особенности, которые нужно учитывать при использовании пакетной выборки строк.

  • Реализация блочного обмена полей записей.

Поддержка пакетной выборки строк в классе CRecordset

Перед открытием объекта набора записей необходимо задать размер набора строк с помощью функции-члена SetRowsetSize. Размер набора строк определяет, сколько записей должно быть извлечено за одну операцию выборки. Если пакетная выборка строк реализована, по умолчанию размер набора строк равен 25, а если не реализована, то размер набора строк остается равным 1.

После установки размера набора строк вызовите функцию-член Open. Чтобы реализовать пакетную выборку строк, этой функции в составе параметра dwOptions необходимо передать параметр CRecordset::useMultiRowFetch. Дополнительно можно установить параметр CRecordset::userAllocMultiRowBuffers. Механизм блочного обмена полей записей использует массивы для хранения групп строк данных, извлекаемых операцией выборки. Буферы хранения могут быть выделены автоматически средой выполнения или вручную пользователем. Указание параметра CRecordset::userAllocMultiRowBuffers означает, что за выделение буферов отвечает пользователь.

В следующей таблице перечислены функции-члены класса CRecordset, предназначенные для поддержки пакетной выборки строк:

Функция-член

Описание

CheckRowsetError

Виртуальная функция, обрабатывающая любые ошибки, которые произошли при выполнении выборки.

DoBulkFieldExchange

Реализует блочный обмен полей записей. Вызывается автоматически для передачи групп строк данных из источника данных в объект набора записей.

GetRowsetSize

Извлекает текущее значение размера набора строк.

GetRowsFetched

Сообщает, сколько строк было в действительности извлечено после операции выборки. В большинстве случаев это значение равно размеру набора строк, за исключением выборки неполного набора строк.

GetRowStatus

Возвращает статус выборки для конкретной строки в наборе.

RefreshRowset

Обновляет данные и статус конкретной строки в наборе.

SetRowsetCursorPosition

Перемещает курсор на конкретную строку в наборе.

SetRowsetSize

Виртуальная функция, которая устанавливает новое значение размера набора строк.

Особенности использования пакетной выборки строк

Пакетная выборка строк дает выигрыш в скорости, однако при этом некоторые возможности реализуются по-другому. Перед тем, как принять решение об использовании пакетной выборки строк, необходимо принять во внимание следующее:

  • Среда выполнения автоматически вызывает функцию-член DoBulkFieldExchange для передачи данных из источника данных в объект набора записей. Тем не менее, данные не передаются из набора записей обратно в источник данных. Вызов функций-членов AddNew, Edit, Delete или Update приведет к возникновению ошибки при проверке утверждения. Хотя текущая реализация класса CRecordset не предоставляет механизма обновления пакетов строк данных, пользователи могут написать собственные методы, использующие функцию SQLSetPos интерфейса ODBC API. Дополнительные сведения о функции SQLSetPos см. в справочнике программиста ODBC SDK в документации MSDN.

  • Функции-члены IsDeleted, IsFieldDirty, IsFieldNull, IsFieldNullable, SetFieldDirty и SetFieldNull нельзя использовать с наборами записей, реализующими пакетную выборку строк. Тем не менее, можно использовать GetRowStatus вместо IsDeleted и GetODBCFieldInfo вместо IsFieldNullable.

  • Операции Move перемещают набор записей по набору строк. Пусть, к примеру, был открыт набор из 100 записей с начальным размером набора строк, равным 10. Функция Open извлекает строки с 1 по 10, при этом текущая запись помещается на строку 1. Вызов функции MoveNext приведет к выборке следующего набора строк, а не следующей строки. Этот набор строк содержит строки с 11 по 20, при этом текущая запись помещается на строку 11. Обратите внимание, что при реализации пакетной выборки строк функции MoveNext и Move( 1 ) не эквивалентны друг другу. Функция Move( 1 ) извлекает набор строк, который начинается с первой строки относительно текущей записи. В этом примере вызов функции Move( 1 ) после Open приведет к извлечению набора строк, который будет состоять из строк со 2 по 11, при этом текущая запись позиционируется на строку 2. Дополнительные сведения см. в описании функции-члена Move.

  • Мастера поддерживают простой обмен полей записей, но не поддерживают блочный обмен полей записей. Это означает, что необходимо вручную объявить члены-поля данных и переопределить функцию DoBulkFieldExchange, используя вызовы функций Bulk RFX. Дополнительные сведения см. в разделе Функции обмена полей записей справки по библиотеке классов.

Реализация блочного обмена полей записей

При блочном обмене полей записей набор записей данных передается из источника данных в объект набора записей. Функции 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 d параметре 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. Если набор записей был открыт путем передачи в функцию Open инструкции SQL или хранимой процедуры, порядок, в котором производятся вызовы функций 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(ru-ru,VS.90).gifПримечание.

Перед тем, как экземпляр класса, производного от CRecordset, выйдет из области видимости, необходимо вызвать функцию-член Close. Это необходимо, чтобы освободить всю память, выделенную средой выполнения. Хорошей практикой в программировании является повсеместный явный вызов функции Close, независимо от того, реализуется ли пакетная выборка строк или нет.

Дополнительные сведения об обмене полей записей см. в разделе Обмен полей записей: как работает RFX. Дополнительные сведения об использовании параметров см. в разделах CFieldExchange::SetFieldType и Набор записей: параметризация набора записей (ODBC).

См. также

Основные понятия

Набор записей (ODBC)

Ссылки

CRecordset::m_nFields

CRecordset::m_nParams