2013-03-01 28 views
10

在我的程序開始時,我需要將數據從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_NameDatanew char[nRowsetSize * nMaxLength]

這意味着m_NameData只是一個字符數組!我需要獲取多個名稱,所以我不需要一個2D字符數組?最奇怪的是,RFX_Text_Bulk()初始化我的m_NDCDataLengthsnew long[nRowsetSize]。爲什麼在世界上一個字符數組需要一個長度數組?

+0

數據庫中「[NAME]」字段的大小是多少? – Goldorak84 2013-04-01 13:38:52

+0

@ Goldorak84,最多15個字符。 – 2013-04-02 10:28:55

+0

實際上,m_NameData表示一個字符數組的數組。 m_NDCDataLengths表示m_NameData中的每個字符串的長度。 – Goldorak84 2013-04-02 13:59:13

回答

2

你幾乎說得沒錯。爲了獲取價值, 我會改變你的

 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選項

EDIT 2 :您還可以保留CRecordset :: forwardonly,但添加CRecordset :: useExtendedFetch選項

+0

我確實嘗試過。問題是,'rowsFetched'總是1! – 2013-04-02 15:10:09

+0

您連接的是哪種數據庫? – Goldorak84 2013-04-02 15:31:46

+0

這是一個MS Access數據庫(.mdb) – 2013-04-02 15:37:45

3

根據http://msdn.microsoft.com/en-us/library/77dcbckz.aspx#_core_how_crecordset_supports_bulk_row_fetching你有電話SetRowsetSize之前的CRecordset打開的CRecordset :: useMultiRowFetch標誌:

要實現批量取行,你必須指定的的dwOptions參數 的CRecordset :: useMultiRowFetch選項 打開會員功能。要更改行集大小的設置,請撥打 SetRowsetSize。

+0

該鏈接似乎被破壞。也可以從[此MSDN文章](http://msdn.microsoft.com/zh-cn/library/77dcbckz(v = vs80).aspx),'在初始化行集大小後,調用Open成員函數。在這裏你必須指定CRecordset :: useMultiRowFetch選項。這似乎是矛盾的。 – 2013-03-05 09:22:51

+1

我已修復鏈接。是的,你是對的。嘗試檢查是否實現了批量獲取 - 在SetRowsetSize之前調用GetRowsetSize:{quote}在打開記錄集對象之前,可以使用SetRowsetSize成員函數定義行集大小。行集大小指定在單個提取期間應檢索多少條記錄。當實現批量行讀取時,默認行集大小爲25.如果未實施批量行讀取,則行集大小保持固定爲1. {quote} – AnatolyS 2013-03-05 09:32:52

+0

行集大小似乎設置正確。目前我將它設置爲25。 'GetRowsetSize()'也返回25。 – 2013-03-05 09:52:33

0

剛剛面臨同樣的問題。 您應該使用recset.Open()呼叫dwOptions參數只有CRecordset::useMultiRowFetch,而不是CRecordset::readOnly | CRecordset::useMultiRowFetch。 希望這可以幫助別人......

編輯: -後重新檢查這裏的情況是 - 使用大容量記錄,並與CRecordset::forwardOnlyCRecordset::readOnly開放時,你還必須在dwOptions指定CRecordset::useExtendedFetch。對於其他類型的滾動,使用CRecordset::readOnly | CRecordset::useMultiRowFetch就好了。