Accessing Metadata from Components with Different Versions
The metadata storage service stores replica and item metadata in a lightweight database. The metadata is stored in a specific table schema and binary format that might change as new versions of Sync Framework are released. Additionally, custom provider fields in the database might change as a developer releases new versions of a particular provider. To enable better interoperability between different versions, Sync Framework provides a canonical file format and the SyncMetadataStoreSerializer class (for managed code) or ISyncMetadataStoreSerializer interface (for unmanaged code), which are forward and backward compatible across a reasonable range of metadata changes between versions.
Sync Framework also provides support for upgrading the metadata store. For more information, see Upgrading the Metadata Store Version.
Using the Canonical Format for Version Compatibility
One of the key benefits of a canonical format is the ability for partial participant replicas, such as devices, to synchronize with different versions of a provider. Consider the following example:
An application supports synchronization between a device and a number of servers at a variety of corporate offices. Users can synchronize a device with a server, make changes on the device, synchronize with a server at another office, and so on.
The company's contacts provider has been released in three different versions: 1.0, 2.0, and 2.5. Version 1.0 is based on Sync Framework 1.0, and the other two versions are based on Sync Framework 2.0. All three of these versions are still available and supported on the corporate network.
Sync Framework Versioning
If the application stores metadata in a metadata storage service binary file on the device, the metadata schema and format might be incompatible with the provider that a user wants to synchronize with. This incompatibility can arise either because the provider is a different version and uses a different metadata file format or because the provider uses a different version of Sync Framework. To avoid this issue, the application could instead use a binary file on each server and then serialize and deserialize metadata between this file and a canonical file on each device. The process is as follows:
When the first synchronization session for a device is complete, the application serializes metadata to a canonical file on the device by calling SerializeReplicaMetadata(SyncIdFormatGroup, SyncId, String, SyncSerializationVersion) (for managed code) or ISyncMetadataStoreSerializer::SerializeReplicaMetadata (for unmanaged code).
During each subsequent session, the application performs the following actions:
Calls DeserializeReplicaMetadata(String, UInt32, IProviderUpgradeCallback) (for managed code) or ISyncMetadataStoreSerializer::DeserializeReplicaMetadata (for unmanaged code) to deserialize metadata from the canonical file and apply it to the binary file on the server.
Synchronizes changes between the device and server.
Calls SerializeReplicaMetadata(SyncIdFormatGroup, SyncId, String, SyncSerializationVersion) (for managed code) or SerializeReplicaMetadata (for unmanaged code) to serialize updated metadata back to the device.
The serialization and deserialization processes are efficient: for serialization, the queries that select metadata from the metadata storage service store are indexed; for deserialization, only incremental changes to the canonical file are deserialized.
The SyncMetadataStoreSerializer class (for managed code) and ISyncMetadataStoreSerializer interface (for unmanaged code) methods support provider versioning by serializing the provider version as part of the metadata and checking the expected provider version when the metadata is deserialized. Consider the following scenario:
There are three versions of a provider (v1, v2, and v3).
In v2, an incompatible change was made to the custom schema for the provider.
v2 and v3 are compatible.
If you serialize metadata from a v3 provider, you could specify a value of v2 for the provider version in the metadata. A v2 or v3 provider can then deserialize metadata by specifying a value of v2 for the expected provider compatibility version parameter. The v1 provider would specify a value of v1, and deserialization would fail by design because the metadata is incompatible with v1. In general, use the lowest version possible to ensure the highest level of compatibility with previous versions of the same provider.
When you release a new version of a provider that upgrades the metadata schema, you must take care to maintain metadata compatibility with earlier provider versions. For more information, see Upgrading the Metadata Store Version.