实现批量记录获取
在我的程序开始时,我需要将 MS Access 数据库 (.mdb) 中的数据读取到下拉控件中.这样做是为了在用户输入该控件时,应用程序可以自动完成.
At the start of my program, I need to read data from a MS Access database (.mdb) into a drop down control. This is done so that whenever the user types in that control, the application can auto-complete.
无论如何,从数据库中读取数据需要很长时间,所以我想我应该实现批量行获取.
Anyway, the reading from database took forever so I thought I'd implement bulk row fetching.
这是我的代码:
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
看起来像:
And in my database, the INFOTABLE
looks like:
NAME AGE
---- ---
Name1 Age1
Name2 Age2
.
.
.
.
我需要做的只是读取数据库中的数据.有人可以告诉我我做错了什么吗?我的代码现在的行为与正常提取完全一样.不会发生批量提取.
All I need to do is only read the data from the database. Can someone please tell me what I'm doing wrong? My code right now behaves exactly like a normal fetch. There's no bulk fetching happening.
我刚刚在 DBRFX.cpp
中闲逛,发现 RFX_Text_Bulk()
将我传递的 m_NameData
初始化为 new char[nRowsetSize * nMaxLength]
!
I just poked around in DBRFX.cpp
and found out that RFX_Text_Bulk()
initializes my passed m_NameData
as new char[nRowsetSize * nMaxLength]
!
这意味着 m_NameData
只是一个字符数组!我需要获取多个名称,所以我不需要二维字符数组吗?最奇怪的是,同样的 RFX_Text_Bulk()
将我传递的 m_NDCDataLengths
初始化为 new long[nRowsetSize]
.为什么一个字符数组需要一个长度数组?!
This means m_NameData
is only a character array! I need to fetch multiple names, so wouldn't I need a 2D character array? The strangest thing is, the same RFX_Text_Bulk()
initializes my passed m_NDCDataLengths
as new long[nRowsetSize]
. Why in the world would a character array need an array of lengths?!
推荐答案
你几乎做对了.要获取值,我会改变你的
You almost got it right. To fetch the values, I would change your
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 选项
To fetch more than one row, remove the CRecordset::forwardOnly option
编辑 2:您也可以保留 CRecordset::forwardonly,但添加 CRecordset::useExtendedFetch 选项
EDIT 2 : You can also keep CRecordset::forwardonly, but add the CRecordset::useExtendedFetch option
相关文章