实现批量记录取(Implementing bulk record fetching)

2019-08-17 05:45发布

在我的节目开始时,我需要从一个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
      .
      .
      .
      .

我需要做的仅仅是从数据库中读取数据。 有人可以告诉我,我做错了什么? 我的代码现在的行为完全像一个正常的获取。 有没有bulk获取发生。

编辑:

我只是戳周围DBRFX.cpp并发现RFX_Text_Bulk()初始化我通过m_NameData作为new char[nRowsetSize * nMaxLength]

这意味着m_NameData只是一个字符数组! 我需要获取多个名称,所以不会,我需要一个二维字符数组? 最奇怪的是,同样的RFX_Text_Bulk()初始化我通过m_NDCDataLengths作为new long[nRowsetSize] 为什么在世界上会的字符数组需要长度的阵列?

Answer 1:

你几乎是正确的。 为了获取价值,我会改变你的

        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选项



Answer 2:

据http://msdn.microsoft.com/en-us/library/77dcbckz.aspx#_core_how_crecordset_supports_bulk_row_fetching你必须与呼叫SetRowsetSize之前的CRecordset :: useMultiRowFetch标志打开的CRecordset:

为了实现批量取行,你必须指定Open成员函数的dwOptions参数的CRecordset :: useMultiRowFetch选项。 要更改行集合大小的设置,调用SetRowsetSize。



Answer 3:

只是面临同样的问题。 你应该使用recset.Open()呼吁dwOptions参数只CRecordset::useMultiRowFetch ,而不是CRecordset::readOnly | CRecordset::useMultiRowFetch CRecordset::readOnly | CRecordset::useMultiRowFetch 。 希望这可以帮助别人...

编辑: -后这里重新检查的情况是-使用大容量记录,并与开放时CRecordset::forwardOnlyCRecordset::readOnly ,你还必须指定CRecordset::useExtendedFetchdwOptions 。 对于其他类型的滚动的,使用CRecordset::readOnly | CRecordset::useMultiRowFetch CRecordset::readOnly | CRecordset::useMultiRowFetch就好了。



文章来源: Implementing bulk record fetching