Microsoft KB Archive/197448

= FIX: CRecordset "String Cannot Be Converted to Number" Error =

Article ID: 197448

Article Last Modified on 12/11/2003

-

APPLIES TO


 * Microsoft Visual C++ 5.0 Enterprise Edition
 * Microsoft Visual C++ 6.0 Enterprise Edition
 * Microsoft Open Database Connectivity 3.0
 * Microsoft Open Database Connectivity 3.5
 * Microsoft Open Database Connectivity 3.51
 * Microsoft Open Database Connectivity 3.6

-



This article was previously published under Q197448



SYMPTOMS
This article explains the consequences of altering the address assigned to a CRecordset member variable. This problem can occur when the CRecordset class uses numeric or decimal fields. If the internal buffer changes, the following error message can occur during a call to CRecordset::Update:

String cannot be converted to number



CAUSE
Each field in a database that is bound to a CRecordset member variable has a corresponding binding address stored in CRecordset::m_pvBindAddress. This binding address is the location in memory where data for each field is placed when ODBC retrieves a record. Once bound, the address of this column must remain valid as long as the ODBC binding remains in effect. If this address changes, the CRecordset class can display the following debug TRACE message when retrieving a record:

Error: field address (column x) has changed

If the field in question is a high precision numeric or decimal field, the following error may occur while performing a CRecordset::Update:

String cannot be converted to number



RESOLUTION
The MFC CRecordset Class Wizard binds high precision numeric and decimal fields to CString member variables. The MFC CRecordset class keeps a pointer to the CString internal buffer in CRecordset::m_pvBindAddress. If you modify a CString member variable, the CString class may re-allocate it's string buffer (for example, if you increase the size of the CString). If this change occurs, the address stored in CRecordset::m_pvBindAddress becomes invalid.

For example, the CString class can reallocate its internal memory if you make the following call to CString::Format(...): CString strNumber; strNumber.Format( "%6.3f", 123456.123 ); To ensure your CString buffer is large enough, pass a larger value than the default of 255 to the fourth parameter of RFX_Text (nMaxLength). For example, the following code demonstrates the before and after of an RFX_Text call: // BEFORE void CMyRecordsSet::DoFieldExchange(CFieldExchange* pFX) {     //AFX_FIELD_MAP }

// AFTER void CMyRecordsSet::DoFieldExchange(CFieldExchange* pFX) {     //AFX_FIELD_MAP }



STATUS
Microsoft has confirmed that this is a bug in the Microsoft products that are listed at the beginning of this article.

This bug was corrected in Visual Studio 6.0 Service Pack 3. For more information about Visual Studio service packs, please see the following articles in the Microsoft Knowledge Base:

194022 INFO: Visual Studio 6.0 Service Packs, What, Where, Why

194295 HOWTO: Tell That Visual Studio 6.0 Service Packs Are Installed



MORE INFORMATION
Internally, the CRecordset class checks CRecordset::m_pvBindAddress against the class member field buffer to ensure it has not changed. If this comparison fails, you get the "String cannot be converted to number" error.

The comparison is made in dbrfx.cpp on line 1049: if (pvBind != pInfo->m_pvBindAddress) {

TRACE1("Error: CString buffer (column %u) address has changed!\n",     nField); ASSERT(FALSE);

}

Keywords: kberrmsg kbbug kbfix kbdatabase kbdriver kbcode kbvs600sp3fix KB197448

-

[mailto:TECHNET@MICROSOFT.COM Send feedback to Microsoft]

© Microsoft Corporation. All rights reserved.