SAMPLE: Using Dynasets with the 16-Bit MFC Database Classes

Last reviewed: July 17, 1997
Article ID: Q124915
The information in this article applies to:

   The Microsoft Foundation Classes (MFC) included with:
     - Microsoft Visual C++ for Windows, version 1.51, 1.52

SUMMARY

With some additional code, dynasets may be used with the MFC 2.51 or 2.52. This sample contains the following components:

   DYNA.H          - Single header file used by next three files
   DYNACORE.CPP    - Defines CDynaRecordset and CDynaDatabase
   DYNARFX.CPP     - Defines new RFX functions
   DYNAVIEW.CPP    - Defines CDynaRecordView
   ENROLL          - Modified ENROLL Step 3 sample that
                     demonstrates how the code can be used.

To successfully use this code, you must have:
  • An ODBC driver that supports keyset-driven cursors and SQLSetPos() functionality (see below for more information)
  • Visual C++ version 1.51 (contains newer header files)
  • The ODBC 2.1 or greater components (see below for more information)

NOTE: The file must be decompressed by typing "DYNSET.EXE -d".

The following file is available for download from the Microsoft Software Library:

 ~ Dynset.exe (size: 64073 bytes) 

For more information about downloading files from the Microsoft Software Library, please see the following article in the Microsoft Knowledge Base:

   ARTICLE-ID: Q119591
   TITLE     : How to Obtain Microsoft Support Files from Online Services

MORE INFORMATION

What Is a Dynaset?

The Visual C++ MFC Encyclopedia in the books online states the following:

   A dynaset is a recordset with dynamic properties. During its lifetime, a
   recordset object in dynaset mode (usually called simply a "dynaset")
   stays synchronized with the data source in the following way. In a
   multiuser environment, other users may edit or delete records that are
   in your dynaset or add records to the table your dynaset represents.
   Records your application updates or deletes from the recordset are
   reflected in your dynaset. Records that other users add to the table
   will not be reflected in your dynaset until you rebuild the dynaset by
   calling its Requery member function. Records that other users delete
   appear as "holes" in your recordset, marked as "deleted." Other users'
   editing changes to existing records are reflected in your dynaset as
   soon as you scroll to the affected record.

   Similarly, edits you make to records in a dynaset are reflected in
   dynasets in use by other users. Records you add are not reflected in
   other users' dynasets until they requery their dynasets. Records you
   delete are marked as "deleted" in others' recordsets. If you have
   multiple connections to the same database (multiple CDatabase objects),
   recordsets associated with those connections have the same status as the
   recordsets of other users. Dynasets are most valuable when data must be
   dynamic, as for an airline reservation system.

What Are the Advantages Of Using Dynasets?

As mentioned above, dynaset recordsets read directly from the data source for each record fetched in the recordset. Therefore the record can change values between subsequent fetches. There are two additional big advantages which dynasets provide: speed and decreased memory usage. By not using snapshots and using dynasets instead, you don't load the cursor library (ODBCCURS.DLL). The cursor library reads each record for a recordset and stores it into memory as you traverse through the records. Thus, it saves the data for that moment in time. This can slow application performance. The cursor library creates temporary files, which are used for storing the temporary records. This uses more memory and disk space which you wouldn't use if you use dynasets. Lastly, the cursor library traps ODBC API calls before they are sent to the driver and this can slow an application.

What Are the Requirements for Using Dynasets?

Not all ODBC drivers support MFC dynasets. For example, the ODBC drivers included with Visual C++ version 1.5, 1.51, and 1.52 do not support dynasets. If you use the ODBC drivers provided with the ODBC 2.0 Desktop Driver Pack and the code provided with this sample, you can utilize dynasets for the desktop drivers (Microsoft Access 2.0, FoxPro, and so forth).

When using this code, it is important that your ODBC driver support the following:

  • Keyset driven cursors
  • SQLSetPos() ODBC 2.0 functionality - SQL_POS_UPDATE, SQL_POS_DELETE, and SQL_POS_ADD

Look at the CDynaRecordset::OnSetOptions() function in DYNACORE.CPP to see the SQLGetInfo() calls that are used to determine if a driver supports MFC dynasets. Specifically, SQL_SO_KEYSET_DRIVEN and SQL_POS_OPERATIONS functionality is checked. If SQL_POS_OPERATIONS isn't supported by the driver, the dynaset can not be modified and therefore will be read-only.

Look at the help file or other documentation for the ODBC driver you're using to discover whether it supports the items mentioned above.

Note, the ODBC drivers that come with Visual C++ 1.5 and 1.51 don't support SQLSetPos(). You must be using the ODBC drivers provided with the ODBC 2.0 Driver pack, or something newer.

How to Use the Code

A modified version of the ENROLL Step 3 tutorial sample is provided. It demonstrates how to use the dynaset code. To use the code do the following:

  • Replace all references to "CRecordset" in your code with "CDynaRecordset".
  • Replace CDatabase objects with CDynaDatabase. The CDynaDatabase class contains an Open() function with a parameter that permits you to conditionally load the cursor library. When you use dynasets, you don't want to load the cursor library.
  • Derive your CRecordView class from CDynaRecordView. The CDynaRecordView contains modified versions of OnInitialUpdate() as well as OnMove(), which require you to use a CDynaRecordset rather than a CRecordset.
  • Replace all RFX function calls in the recordset's DoFieldExchange() function with their related Dyna_RFX... functions included in DYNARFX.CPP. Place the Dyna_RFX... functions outside the ClassWizard tagged section, otherwise ClassWizard will produce a parsing error the next time it tries to read your file. The ClassWizard section is delimited by "//{{AFX_FIELD_MAP(CYourRecordset)" and "//}}AFX_FIELD_MAP".

Why Are the ODBC 2.1 Components Necessary?

The ODBC 2.1 Driver Manager is required to avoid a bug that occurs with the previous versions of the driver manager. If you use the driver manager (ODBC.DLL) included in the ODBC Driver Pack, you will receive an "Invalid Cursor State" error when using dynasets and trying to add a record to a table following an query that produced an empty recordset. In other words, if you open a CRecordset object and the query returns an empty recordset, a subsequent AddNew()/Update() call will cause the error. The ODBC 2.1 driver fixes this problem. The ODBC 2.1 components shipped with Visual C++ 1.52.

REFERENCES

For more information about the ODBC functions used, see the ODBC 2.0 Programmer's Reference. This is included in the Visual C++ version 2.0 online books.


Additional query words: dynamic dyna set record set helpfile
‘* to NULL with Snapshots” Q155591. If you modify or delete either of these
Keywords : kb16bitonly kbfile kbprg kbsample MfcDatabase
Technology : kbMfc
Version : 1.51 1.52
Platform : WINDOWS


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: July 17, 1997
© 1998 Microsoft Corporation. All rights reserved. Terms of Use.