FIX: Edit() After Requery() May Produce Incorrect Results

Last reviewed: September 18, 1997
Article ID: Q116409
1.50 WINDOWS kbprg kbfixlist kbbuglist

The information in this article applies to:

  • The Microsoft Foundation Classes (MFC), included with:

        - Microsoft Visual C++ for Windows, version 1.5
    

SYMPTOMS

In an MFC database application using CRecordsets:

  1. Open a recordset and look at the contents of the first record.

  2. Call Edit() on the recordset object to place it in Edit mode.

  3. Change the parameters for the query.

  4. Call Requery() on the recordset with a different query so that a different record appears as the first record.

  5. Call Edit() on the new recordset and notice that the fields are loaded with the values from the first record of the first recordset.

  6. Inspect the field variables of the recordset and note that they contain the values of the original query instead of the new values you would expect.

CAUSE

The reason for this behavior is that Requery() does not reset the m_nEditMode variable that gets set when you call Edit(), nor does it flush the CMemFile-based record cache. The second time Edit() is called, m_nEditMode indicates that the recordset is in Edit mode and therefore is reset, with the cache restored to the record fields. This behavior of the second call to Edit() is expected according to the specification of the function [see the Edit() function description in the "MFC Library Reference"].

RESOLUTION

To work around this, override CRecordset::Requery() in your derived CRecordset class and call the ReleaseCopyBuffer() function. This resets the Edit-mode member variable, m_nEditMode, and also flushes the record cache. The sample code in the "MORE INFORMATION" section, below, includes an example of an overridden Requery().

STATUS

Microsoft has confirmed this to be a bug in the Microsoft products listed at the beginning of this article. This problem was corrected in MFC version 2.51, included with Visual C++ version 1.51.

MORE INFORMATION

The CRecordset class contains two member variables called "m_pmemfile" and "m_par". m_pmemfile is a pointer to a CMemFile object used to hold the current record; m_par is a pointer to an archive used to hold the CMemFile. m_pmemfile is the cache that remains persistent between calls to "Edit()" if no reopen or requery is done. "ReleaseCopyBuffer()" frees the objects associated with these pointers and thus flushes any values that might be restored on a second edit call. Edit() then reallocates the CMemFile object and archive and reloads the cache buffer.

Sample Code

// CMyRecordset is derived from CRecordset.

   BOOL CMyRecordset::Requery()
   {
       BOOL bRC = CRecordset::Requery();
       ReleaseCopyBuffer();
       return bRC;
   }

REFERENCES

For other articles pertaining to problems with CRecordset::Requery(), query on "Requery" and "CRecordset".


Additional reference words: InitRecord 1.50 2.50
KBCategory: kbprg kbfixlist kbbuglist
KBSubcategory: MfcDatabase
Keywords : kb16bitonly MfcDatabase kbbuglist kbfixlist kbprg
Technology : kbMfc
Version : 1.50
Platform : WINDOWS
Solution Type : kbfix


THE INFORMATION PROVIDED IN THE MICROSOFT KNOWLEDGE BASE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. MICROSOFT DISCLAIMS ALL WARRANTIES, EITHER EXPRESS OR IMPLIED, INCLUDING THE WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL MICROSOFT CORPORATION OR ITS SUPPLIERS BE LIABLE FOR ANY DAMAGES WHATSOEVER INCLUDING DIRECT, INDIRECT, INCIDENTAL, CONSEQUENTIAL, LOSS OF BUSINESS PROFITS OR SPECIAL DAMAGES, EVEN IF MICROSOFT CORPORATION OR ITS SUPPLIERS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. SOME STATES DO NOT ALLOW THE EXCLUSION OR LIMITATION OF LIABILITY FOR CONSEQUENTIAL OR INCIDENTAL DAMAGES SO THE FOREGOING LIMITATION MAY NOT APPLY.

Last reviewed: September 18, 1997
© 1998 Microsoft Corporation. All rights reserved. Terms of Use.