在我的程序开始时,我需要从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,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初始化为新的char [nRowsetSize * nMaxLength]!
这意味着m_NameData只是一个字符数组!我需要获取多个名称,所以不需要一个2D字符数组?最奇怪的是,同样的RFX_Text_Bulk()会将传递的m_NDCDataLength初始化为new long [nRowsetSize].为什么在世界上一个字符数组需要一个长度的数组?
解决方法
你差点就对了要获取值,
我会改变你的
我会改变你的
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选项