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

ID: Q116409

1.50 WINDOWS kbprg kbfixlist kbbuglist

The information in this article applies to:

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 kbDatabase kbMFC kbODBC kbVC kbbuglist kbfixlist
Version           : 1.50
Platform          : WINDOWS
Solution Type     : kbfix

Last Reviewed: September 21, 1997