2013-03-01 22 views
10

getirilirken toplu kayıt uygulanması, kontrolüm bir açılır içine MS Access veritabanı (.mdb) veri okumak gerekiyor. Bu, kullanıcı bu denetimde her yazdığında, uygulamanın otomatik tamamlayabilmesi için yapılır. Ben getirilirken toplu satır uygulamak düşündüm bu yüzdenbenim Programın başında

Neyse, veritabanından okuma sonsuza kadar sürdü.

#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 

Ve veritabanında

, INFOTABLE benziyor:

#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 benziyor:

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 benziyor:

Bu

Ben kodudur:

Tüm yapmam gereken veriden yalnızca okuyor. Birisi bana neyi yanlış yaptığımı söyler mi? Kodum şu anda normal bir getirme gibi davranıyor. Toplu alım yok.

EDIT: Sadece DBRFX.cpp etrafında dürttü ve RFX_Text_Bulk() benim new char[nRowsetSize * nMaxLength] olarak m_NameData geçti başlatır öğrendim

!

Bu, m_NameData'un yalnızca bir karakter dizisi olduğu anlamına gelir! Birden çok isim almam gerekiyor, bu yüzden 2B karakter dizisine ihtiyacım olmaz mı? En garip şey, aynı RFX_Text_Bulk(), m_NDCDataLengths iletimi new long[nRowsetSize] olarak başlatır. Neden dünyadaki bir karakter dizisi bir dizi diziye ihtiyaç duyardı ?!

+0

Veritabanınızdaki "[NAME]" alanının boyutu nedir? – Goldorak84

+0

@ Goldorak84, en fazla 15 karakter. –

+0

Aslında, m_NameData bir dizi karakter dizisini temsil eder. m_NDCDataLengths, m_NameData – Goldorak84

cevap

2

Neredeyse doğru var. değerlerini getirmek için, senin bu

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); 
} 

DÜZENLEME gibi bir şey tarafından

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

değiştirecek: CRecordset, birden fazla satır getirme kaldırmak için :: forwardOnly seçenek

EDIT 2 : Ayrıca :: forwardonly CRecordset tutmak, ancak CRecordset :: useExtendedFetch seçeneği Sadece aynı problemle karşılaşan

+0

Bunu denedim. Sorun şu ki, 'farelerFetched' her zaman 1! –

+0

Ne tür bir veritabanına bağlanıyorsunuz? – Goldorak84

+0

Bir MS Access veritabanı (.mdb) –

3

http://msdn.microsoft.com/en-us/library/77dcbckz.aspx#_core_how_crecordset_supports_bulk_row_fetching göre sen CRecordset ile CRecordset açmak için :: useMultiRowFetch bayrağı çağrı SetRowsetSize önce var:

Toplu satır alma yeteneğiniz uygulamak için, bir dwOptions parametresinde CRecordset :: useMultiRowFetch seçeneği belirtmelisiniz Üye işlevini aç. satır kümesi boyutu için ayarı değiştirmek için SetRowsetSize diyoruz.

+0

olarak sıfırlayabilir. Bu bağlantı bozuk görünüyor. Ayrıca [bu MSDN makalesinden] (http://msdn.microsoft.com/en-us/library/77dcbckz (v = vs80) .aspx), 'Satır kümesi boyutunu başlattıktan sonra Open member işlevini çağırın. . Burada CRecordset :: useMultiRowFetch seçeneğini belirtmeniz gerekir. Bu çelişkili görünüyor. –

+1

Bağlantıyı düzelttim. Evet haklısın. Toplu alım gerçekleştirildiğini kontrol etmeye çalışın - SetRowsetSize'den önce GetRowsetSize çağırın: {quote} Kayıt kümesi nesnesini açmadan önce, SetRowsetSize üye işleviyle bir satır kümesi boyutu tanımlayabilirsiniz. Satır boyutu, tek bir getirme sırasında kaç kayıt alınacağını belirtir. Toplu satır getirme uygulandığında, varsayılan satır kümesi boyutu 25'tür. Toplu satır getirme uygulanmazsa, satır kümesi boyutu 1'de sabit kalır. {Quote} – AnatolyS

+0

Satır boyutu doğru ayarlanmış gibi görünüyor. Şu an 25'e ayarlıyorum. 'GetRowsetSize()' da 25 değerini döndürür. –

0

ekleyebilir. dwOptionsCRecordset::useMultiRowFetch için numaralı çağrıyı kullanmalısınız ve CRecordset::readOnly | CRecordset::useMultiRowFetch değil. Bu birileri yardımcı olur Umut ...

DÜZENLEME: - Sonra tekrar kontrol Burada durum - toplu kayıt ve CRecordset::forwardOnly ve CRecordset::readOnly ile açılmasını kullanırken, ayrıca dwOptions yılında CRecordset::useExtendedFetch belirtmelisiniz. Diğer kaydırma türleri için CRecordset::readOnly | CRecordset::useMultiRowFetch kullanımı gayet iyi.

İlgili konular