INF: How to Implement Schemas or CObject Versioning in MFC
PSS ID Number: Q108370
Article last modified on 02-18-1994

1.00 2.00 2.50

WINDOWS


---------------------------------------------------------------------
The information in this article applies to:

 - Microsoft Foundation Classes for Windows, versions 1.0, 2.0,
   and 2.5
---------------------------------------------------------------------

SUMMARY
=======

Versioning CObject- and CObject-derived classes must be implemented without
the use of the "wSchema" parameter in IMPLEMENT_SERIAL() if you have more
than two versions. Versioning can be implemented manually by using a member
variable in the class to be serialized.

MORE INFORMATION
================

Processing the CArchiveException::badSchema exception when reading in a
CObject-derived object tells you only that the serialized object is not the
same version of the class as it was compiled in this version of your
application. If you have only two versions of a class, then read the new
version if no exception is thrown; read the old version in your CATCH block
if an exception is thrown.

If you have more than two versions of your class, schema s won t work. With
a CArchiveException::badSchema, there is no information that tells which
version of the object to read in. The only way to work around this is to
implement the schema concept within the class by using a version member
variable and checking that variable before reading the object.

Microsoft Foundation Classes (MFC) Tech Note #2 "Persistent Object Data
Format" contains additional information regarding serialization and MFC s
implementation of persistent object storage.

The following sample code illustrates the two methods described above.
Example A assumes only two versions of the object class. Example B assumes
multiple versions and also assumes that the class has left the wSchema
argument to the IMPLEMENT_SERIAL() the same for each version [that is,
IMPLEMENT_SERIAL(CMyObject, CObject, 1)] so that no exception is generated
even when reading an older versioned object.

Sample Code
-----------

The samples presented in this section are not intended to be compiled as
standalone programs. These are sample serialize functions that can be used
models for implementing your own version-aware serialization code.

// Example A - Assume only two versions and use "CArchive::badSchema".

CMyObject::Serialize(CArchive& ar)
{
    LONG lFile = ar.GetFile()->GetCurrentPosition();
    if (ar.IsStoring())
    {
        // Write out the new version of the
        // CMyObject.
    }
    else
    {
        TRY
        {
            // Read in new version of the CMyObject.
        }
        CATCH (CArchiveException, e)
        {
            if (e.Cause == CArchiveException::badSchema)
            {
                ar.Flush();
                ar.GetFile()->Seek(lFile, CFile::begin);
                // Read in the old version of CMyObject.
            }
        }
        END_CATCH
    }
}

// Example B - Assume multiple versions and implement schema in
// class.  Don t use CArchive::badSchema.

CMyObject::Serialize(CArchive& ar)
{
    if (IsStoring())
    {
        ar << (BYTE) 3;      // This is version 3 of the class.
        ar << m_nMyDword;
    }
    else
    {
        BYTE bVer;
        ar >> bVer;        // Read in the version.
        switch( bVer )
        {
            case 3:        // Current version.
                ar >> m_nMyDword;
            case 2:        // Previous version.
                {
                WORD wtemp;
                ar >> wtemp;
                m_nMyDword = wtemp;  // Convert.
                }
            case 1:        // Original version.
                {
                BYTE btemp;
                ar >> btemp;
                m_nMyDword = btemp; // Convert.
                }
            default:
        }
    }
}

Additional reference words: 1.00 2.00 2.50 CArchive badSchema serialize
KBCategory: APrg
KBSubcategory:

=============================================================================

Copyright Microsoft Corporation 1994.
