Реализация массовой выборки записей

В начале моей программы мне нужно прочитать данные из базы данных MS Access (.mdb) в выпадающий элемент управления. Это сделано для того, чтобы каждый раз, когда пользователь вводил данные в этот элемент управления, приложение могло автоматически завершаться.

Во всяком случае, чтение из базы данных заняло вечность, поэтому я подумал, что я буду осуществлять массовую выборку строк.

Вот код, который у меня есть:

CString sDsn;
CString sField;
sDsn.Format("ODBC;DRIVER={%s};DSN='';DBQ=%s",sDriver,sFile);
TRY
{
// Open the database
database.Open(NULL,false,false,sDsn);

// Allocate the rowset
CMultiRowset recset( &database );

// Build the SQL statement
SqlString =  "SELECT NAME ""FROM INFOTABLE";

// Set the rowset size. These many rows will be fetched in one bulk operation
recset.SetRowsetSize(25);

// Open the rowset
recset.Open(CRecordset::forwardOnly, SqlString, CRecordset::readOnly | CRecordset::useMultiRowFetch);

// Loop through each rowset
while( !recset.IsEOF() )
{
int rowsFetched = (int)recset.GetRowsFetched(); // This value is always 1 somehow
for( int rowCount = 1; rowCount <= rowsFetched; rowCount++ )
{
recset.SetRowsetCursorPosition(rowCount);
recset.GetFieldValue("NAME",sField);
m_nameDropDown.AddString(sField);
}

// Go to next rowset
recset.MoveNext();
}

// Close the database
database.Close();
}
CATCH(CDBException, e)
{
// If a database exception occured, show error msg
AfxMessageBox("Database error: "+e->m_strError);
}
END_CATCH;

MultiRowset.cpp похоже:

#include "stdafx.h"#include "afxdb.h"#include "MultiRowset.h"
// Constructor
CMultiRowset::CMultiRowset(CDatabase *pDB)
: CRecordset(pDB)
{
m_NameData = NULL;
m_NameDataLengths = NULL;

m_nFields = 1;
CRecordset::CRecordset(pDB);
}

void CMultiRowset::DoBulkFieldExchange(CFieldExchange *pFX)
{
pFX->SetFieldType(CFieldExchange::outputColumn);
RFX_Text_Bulk(pFX, _T("[NAME]"), &m_NameData, &m_NameDataLengths, 30);
}

MultiRowset.h похоже:

#if !defined(__MULTIROWSET_H_AD12FD1F_0566_4cb2_AE11_057227A594B8__)
#define __MULTIROWSET_H_AD12FD1F_0566_4cb2_AE11_057227A594B8__

class CMultiRowset : public CRecordset
{
public:
// Field data members
LPSTR m_NameData;

// Pointers for the lengths of the field data
long* m_NameDataLengths;

// Constructor
CMultiRowset(CDatabase *);

// Methods
void DoBulkFieldExchange(CFieldExchange *);
};

#endif

И в моей базе данных INFOTABLE похоже:

NAME    AGE
----    ---
Name1   Age1
Name2   Age2
.
.
.
.

Все, что мне нужно сделать, это только читать данные из базы данных. Может кто-нибудь сказать, пожалуйста, что я делаю не так? Мой код сейчас ведет себя точно так же, как обычная выборка. Там нет массового извлечения происходит.

РЕДАКТИРОВАТЬ:

Я просто ковырялся в DBRFX.cpp и узнал, что RFX_Text_Bulk() инициализирует мой пройденный m_NameData как new char[nRowsetSize * nMaxLength]!

Это означает m_NameData это только массив символов! Мне нужно выбрать несколько имен, так что мне не нужен двумерный массив символов? Самое странное, то же самое RFX_Text_Bulk() инициализирует мой пройденный m_NDCDataLengths как new long[nRowsetSize], Зачем в мире массиву символов нужен массив длин ?!

10

Решение

Вы почти поняли это правильно. Чтобы получить значения,
Я бы изменил ваш

        for( int rowCount = 1; rowCount <= rowsFetched; rowCount++ )
{
recset.SetRowsetCursorPosition(rowCount);
recset.GetFieldValue("NAME",sField);
m_nameDropDown.AddString(sField);
}

чем-то вроде этого

for( int nPosInRowset = 0; nPosInRowset < rowsFetched; nPosInRowset++ )
{
//Check if value is null
if (*(recset.m_NameDataLengths + nPosInRowset) == SQL_NULL_DATA)
continue;

CString csComboString;
csComboString = (recset.m_NameData + (nPosInRowset * 30)); //Where 30 is the size specified in RFX_Text_Bulk

m_nameDropDown.AddString(csComboString);
}

РЕДАКТИРОВАТЬ: чтобы получить более одной строки, удалите опцию CRecordset :: forwardOnly

РЕДАКТИРОВАТЬ 2: Вы также можете оставить CRecordset :: forwardonly, но добавьте опцию CRecordset :: useExtendedFetch

2

Другие решения

В соответствии с http://msdn.microsoft.com/en-us/library/77dcbckz.aspx#_core_how_crecordset_supports_bulk_row_fetching Вы должны открыть CRecordset с флагом CRecordset :: useMultiRowFetch перед вызовом SetRowsetSize:

Чтобы реализовать массовую выборку строк, необходимо указать
Опция CRecordset :: useMultiRowFetch в параметре dwOptions объекта
Открытая функция-член. Чтобы изменить настройку размера набора строк, позвоните
SetRowsetSize.

3

Просто столкнулся с той же проблемой.
Вы должны использовать в recset.Open() звать dwOptions только параметр CRecordset::useMultiRowFetch, и не CRecordset::readOnly | CRecordset::useMultiRowFetch,
Надеюсь, это поможет кому-то …

РЕДАКТИРОВАТЬ:- После перепроверки вот такая ситуация — при использовании набора массовых записей и открытии с CRecordset::forwardOnly а также CRecordset::readOnly, вы также должны указать CRecordset::useExtendedFetch в dwOptions, Для других типов прокрутки, используя CRecordset::readOnly | CRecordset::useMultiRowFetch просто отлично.

0
По вопросам рекламы ammmcru@yandex.ru
Adblock
detector