10/07/2009 22:01:58

This Release Notes document describes breaking changes and known issues that you should read about before you install or troubleshoot Microsoft Sync Framework 2.0.

  1. Installing Sync Framework
    1. Uninstall Sync Framework Preview Release Before Installing Final Release
  2. Database Providers
    1. Breaking Changes
    2. Compact() Command Can Cause Non-Convergence of Data
    3. Database Provisioning Can Result in Serialization Errors
    4. Database Provisioning Fails for Windows' Least-Privilege User Account (LUA)
    5. Sample Application Throws a Deserialization Exception
  3. Core Components
    1. Breaking Changes
    2. Some Methods May Return Errors That Do Not Contain a Useful Error Message
    3. Change Units Are Not Restored After a Delete-Update Conflict when Simple Providers and Change Unit Filters Are Used
    4. Filtered Replicas Cannot Perform Full Enumeration for Recovery Synchronization
    5. Tombstone Cleanup on Filtered Replicas Require Additional Processing
    6. Custom Filters Cannot Be Used with Change Units
  4. Documentation and Samples
    1. Samples Must Be Reconfigured to Run on Non-x86 Platform
    2. Some API Members Are Incorrectly Documented
    3. IntelliSense for Chinese Traditional Displays English Text

1. Installing Sync Framework

2. Database Providers

a. Breaking Changes

The following changes occurred between Sync Framework 1.0 and Sync Framework 2.0.

  • The Microsoft.Synchronization.Data.RelationalSyncProvider base class was created to encapsulate the logic that is common across all of the Sync Framework database providers. Many of the members from DbSyncProvider were moved to RelationalSyncProvider, but the overall API surface did not change significantly. Microsoft.Synchronization.Data.DbSyncProvider, Microsoft.Synchronization.Data.SqlServer.SqlSyncProvider, and Microsoft.Synchronization.Data.SqlServerCe.SqlCeSyncProvider all inherit from RelationalSyncProvider.
  • The SyncConflict collection that was available from Microsoft.Synchronization.Data.DbSyncTableProgress has been removed. This was a performance optimization to reduce memory usage for synchronization sessions with a large number of conflicts. It is now recommended to interact with conflicts on an individual basis by using the ApplyChangeFailed event for each provider.

The following changes occurred between Sync Framework 2.0 CTP2 and Sync Framework 2.0 final release version.

  • Removed the Microsoft.Synchronization.Data.SqlServer.SqlSyncProviderAdapterConfiguration.PkColumnNames property. You should now use the Microsoft.Synchronization.Data.SqlServer.SqlSyncProviderAdapterConfiguration.Columns property instead.
  • The following collections were changed to enumerable collections so that they adhere to existing patterns used for popular ADO.Net types such as DataSet:
    • Microsoft.Synchronization.Data.DbSyncTableDescription, which is available through the Microsoft.Synchronization.Data.DbSyncScopeDescription.Tables property.
    • Microsoft.Synchronization.Data.SqlServer.SqlSyncTableProvisioning, which is available through the Microsoft.Synchronization.Data.SqlServer.SqlSyncScopeProvisioning.Tables property.
    • Microsoft.Synchronization.Data.SqlServerCe.SqlCeSyncTableProvisioning, which is available through the Microsoft.Synchronization.Data.SqlServerCe.SqlCeSyncScopeProvisioning.Tables property.
  • The Microsoft.Synchronization.Data.DbSyncColumnDescription.GetInitialParameterName method was converted to a property to conform to API design best practices. You should now use the Microsoft.Synchronization.Data.DbSyncColumnDescription.ParameterName property instead.
  • The name of the snapshot initialization method was changed to Microsoft.Synchronization.Data.SqlServerCe.SqlCeSyncStoreSnapshotInitialization.InitializeFromSnapshot.

b. Compact() Command Can Cause Non-Convergence of Data

c. Database Provisioning Can Result in Serialization Errors

In some cases, Sync Framework uses the XmlIgnoreAttribute attribute when provisioning databases. In older versions of the .NET Framework, the use of XmlIgnoreAttribute results in the following exception:

Message: Unable to generate a temporary class (result=1).
error CS0200: Property or indexer 'Microsoft.Synchronization.Data.DbSyncColumnDescription.IsNullableSpecified' cannot be assigned to -- it is read only
error CS0200: Property or indexer 'Microsoft.Synchronization.Data.DbSyncColumnDescription.IsPrimaryKeySpecified' cannot be assigned to -- it is read only

To avoid this problem, ensure that you have the .NET Framework 2.0 SP1 or later installed on the computer on which the Sync Framework database provider is running.

d. Database Provisioning Fails for Windows' Least-Privilege User Account (LUA)

If the synchronization process is running under LUA, the following error is thrown when attempting to provision a database:

Message: Unable to generate a temporary class (result=1).
error CS2001: Source file 'D:\WINDOWS\TEMP\ycwdmrz3.0.cs' could not be found
error CS2008: No inputs specified

This error occurs because the Xml serializer that Sync Framework uses requires read and write access to the Windows temp directory, which LUA does not allow.

e. Sample Application Throws a Deserialization Exception

When the sample application attempts to set the synchronization batch size to a non-zero value, the following exceptions are thrown:

Outer Exception: An unexpected error occurred when applying batch file.
Inner Exception: Attempting to deserialize an empty stream.

To fix the sample application, modify the GetChangeBatch() method in RelationalProviderProxy.cs (line106) so that the instantiation of the Filestream object is inside the If statement.

//ORIGINAL CODE
string localFileName = Path.Combine(this.localBatchingDirectory.FullName, context.BatchFileName);
FileInfo localFileInfo = new FileInfo(localFileName);

//Download the file only if it doesn't exist
FileStream localFileStream = new FileStream(localFileName, FileMode.Create, FileAccess.Write);

                if (!localFileInfo.Exists)
                {
                    byte[] remoteFileContents = this.proxy.DownloadBatchFile(context.BatchFileName);
                    using (localFileStream)
                    {
                        localFileStream.Write(remoteFileContents, 0, remoteFileContents.Length);
     }
  }

                  }
                }

//UPDATED CODE
string localFileName = Path.Combine(this.localBatchingDirectory.FullName, context.BatchFileName);
FileInfo localFileInfo = new FileInfo(localFileName);
                
                if (!localFileInfo.Exists)
                {
                    //Download the file only if doesnt exist
                    FileStream localFileStream = new FileStream(localFileName, FileMode.Create, FileAccess.Write);
                    byte[] remoteFileContents = this.proxy.DownloadBatchFile(context.BatchFileName);
                    using (localFileStream)
                    {
                        localFileStream.Write(remoteFileContents, 0, remoteFileContents.Length);
     }
  }

3. Core Components

a. Breaking Changes

The following changes occurred between Sync Framework 1.0 and Sync Framework 2.0.

  • The Microsoft.Synchronization.FilterType enumeration (for managed code) and the FILTER_TYPE enumeration (for unmanaged code) are not used and have been removed. Any references to these enumerations in your code must also be removed.

The following changes occurred between Sync Framework 2.0 CTP2 and Sync Framework 2.0 RTM in the Microsoft.Synchronization.SimpleProviders namespace.

  • The following classes and methods were removed.
    • The AnchorEnumerationContext constructor.
    • The AnchorEnumerationSimpleSyncProvider.EnumerateItems method.
    • The ISimpleSyncProviderIdGenerator.GenerateNewReplicaId method.
    • The RecoverableErrorReportingContext.RecordRecoverableErrorForChangeUnit method.
    • The SimpleSyncProvider.ChangeReplicaId method.
    • The ChangeDetectionFailedException class.
    • The CustomConflictResolutionNotSupportedException class.
    • The ItemSchemaNotDefinedException class.
    • The NewItemDoesNotContainAllFieldsException class.
    • The NoCommonChangeUnitsException class.
    • The UnknownChangeUnitException class.
  • The following methods were renamed or parameters were changed.
    • The AnchorEnumerationContext.AutodetectDeletes method was renamed to AnchorEnumerationContext.ReportItemsAndAutodetectDeletes and the method parameters were changed.
    • The AnchorEnumerationSimpleSyncProvider.EnumerateChanges method parameters were changed.
    • The ISimpleSyncProviderIdGenerator.GenerateNewItemId method parameters were changed.
    • The ItemFieldDictionary class no longer implements the System.Collections.ICollection interface.
    • The SimpleSyncServices constructor parameters were changed.
    • The SimpleSyncServices.CleanupTombstones method was renamed to SimpleSyncServices.CleanupDeletedItems.
    • The UnmanagedSimpleSyncProviderWrapper.UnmanagedSimpleSyncProviderWrapper constructor parameters were changed.
    • The UnmanagedSimpleSyncProviderWrapper.Initialize method parameters were changed.
  • The following classes were moved from the Microsoft.Synchronization.SimpleProviders namespace to the Microsoft.Synchronization namespace.
    • ChangeDeferredByProviderException
    • ChangeReplicaIdPendingException
    • DuplicateItemException
    • ItemNotFoundInMetadataStoreException
    • MetadataStoreVersion2RequiredException
    • OptimisticConcurrencyException
    • RecoverableErrorMustFailEntireItemException
    • SimpleProviderInvalidOperationException
    • SimpleProvidersException

b. Some Methods May Return Errors That Do Not Contain a Useful Error Message

Some methods may return a generic error message, such as "Exception from HRESULT: 0x80041006", instead of a description of what caused the error. The following table lists the error codes and their values. For descriptions of these error codes, see Sync Framework Error Codes in the Sync Framework Core Components reference.

Error code Error code value

SYNC_E_ID_FORMAT_MISMATCH

0x80041000

SYNC_E_INVALID_OPERATION

0x80041001

SYNC_E_REPLICA_NOT_FOUND

0x80041002

SYNC_E_CHANGE_COUNT_MISMATCH

0x80041003

SYNC_E_CHANGE_UNIT_COUNT_MISMATCH

0x80041004

SYNC_E_KNOWLEDGE_DECREASED

0x80041005

SYNC_E_CHANGE_NOT_IN_KNOWLEDGE

0x80041006

SYNC_E_ITEM_MUST_EXIST

0x80041007

SYNC_E_HAS_NO_DATA

0x80041008

SYNC_E_CHANGE_NEEDS_KNOWLEDGE

0x80041009

SYNC_E_RANGE_OUT_OF_ORDER

0x8004100A

SYNC_E_NOT_EXPECTED_CHANGE

0x8004100B

SYNC_E_DESERIALIZATION

0x8004100C

SYNC_E_SINGLE_RANGE_ONLY

0x8004100D

SYNC_E_ITEM_HAS_CHANGE_UNITS

0x8004100E

SYNC_E_ITEM_HAS_NO_CHANGE_UNITS

0x8004100F

SYNC_E_ITEM_HAS_NO_VERSION_DATA

0x80041010

SYNC_E_OBJECT_NEEDS_STATE

0x80041011

SYNC_E_FEEDSYNC_INVALID_FEED

0x80041012

SYNC_E_FEEDSYNC_ITEM_NOT_IN_METADATA

0x80041013

SYNC_E_FEEDSYNC_CALLBACK_EXPECTED

0x80041014

SYNC_E_INVALID_VERSION

0x80041015

SYNC_E_DUPLICATE_ITEM

0x80041016

SYNC_E_INVALID_ORDER_FOR_VECTOR_ELEMENTS

0x80041017

SYNC_E_INVALID_SYNC_TIME

0x80041018

SYNC_E_INCOMPLETE_REPLICA_KEY_MAP

0x80041019

SYNC_E_INVALID_REPLICA_KEY

0x8004101A

SYNC_E_NEGATIVE_RANGE_EXCEPTION

0x8004101B

SYNC_E_BATCH_NEEDS_KNOWLEDGE

0x8004101C

SYNC_E_INTERNAL_ERROR

0x8004101D

SYNC_E_CHANGE_BATCH_IS_READ_ONLY

0x8004101E

SYNC_E_DATA_MODIFIED_CONCURRENTLY

0x8004101F

SYNC_E_ON_CREATE_MUST_FAIL_ENTIRE_ITEM

0x80041020

SYNC_E_FILTER_NOT_SUPPORTED

0x80041021

SYNC_E_LOAD_CONFLICT_DATA_FAILED

0x80041022

SYNC_E_INVALID_SERIALIZATION_VERSION

0x80041023

SYNC_E_MARKER_MISMATCH

0x80041024

SYNC_E_FORGOTTEN_KNOWLEDGE_NOT_CONTAINED

0x80041025

SYNC_E_ACTIVE_CHANGE_APPLICATION_CONTEXT

0x80041026

SYNC_E_ITEM_LIST_FILTERED_FULL_ENUMERATION_NOT_SUPPORTED

0x80041027

SYNC_E_FULL_ENUMERATION_MUST_BE_USED

0x80041028

SYNC_E_BATCH_NEEDS_FILTER_FORGOTTEN_KNOWLEDGE

0x80041029

SYNC_E_CONSTRAINT_CONFLICT_NOT_ALLOWED

0x8004102A

SYNC_E_SOURCE_DOES_NOT_TRACK_FILTER

0x8004102B

c. Change Units Are Not Restored After a Delete-Update Conflict when Simple Providers and Change Unit Filters Are Used

This situation occurs when simple providers are used and one of the replicas in the synchronization community uses a change unit filter. The steps that cause this situation are as follows:

  1. Item I is deleted from unfiltered replica A, and the tombstone is then removed.
  2. Item I is updated on replica B. Replica B uses a change unit filter and so does not store all change units for the item.
  3. Synchronization is performed using replica B as the source replica and replica A as the destination replica.
  4. A delete-update conflict is detected on item I and is resolved in favor of the update on replica B. Item I is restored on replica A, but contains data only for the change units that are stored on replica B. The version of all change units is updated to the new version.
  5. Synchronization is again performed, this time using unfiltered replica C as the source replica and replica A as the destination replica.
  6. The missing change units for item I are not sent from replica C, because their versions on replica A are later than their versions on replica C.

To work around this situation, update the change units for item I on replica C so that their versions are later than the versions on replica A, and then synchronize from replica C to replica A.

d. Filtered Replicas Cannot Perform Full Enumeration for Recovery Synchronization

When the destination replica is out-of-date and recovery synchronization must be performed, the source replica must be an unfiltered replica to fully recover the out-of-date replica. When the source replica is a filtered replica, the source provider must not perform a full enumeration or unexpected results may occur.

In this situation, the filtered source replica can perform a partial synchronization with the out-of-date destination replica. To do this, the application specifies FullEnumerationAction.Partial in response to the FullEnumerationNeeded event (for managed code) or SFEA_PARTIAL_SYNC in response to the ISyncCallback::OnFullEnumerationNeeded callback method (for unmanaged code). The application may also cancel synchronization by specifying FullEnumeration.Abort (for managed code) or SFEA_ABORT (for unmanaged code).

e. Tombstone Cleanup on Filtered Replicas Require Additional Processing

When a filtered replica uses the snapshot technique to clean up tombstones, additional care must be taken to ensure the knowledge of the replica always contains the forgotten knowledge of the replica. This is because situations can arise where the knowledge of a filtered replica is reduced because of an item moving in relation to the filter.

Cleaning up tombstones by using managed code

Do not use the snapshot technique when cleaning up tombstones on a filtered replica. Instead, perform the following steps to remove a tombstone:

  1. Call ForgottenKnowledge.ForgetTo, passing the change version of the tombstone to be removed. If this method succeeds, perform step 2.
  2. Remove the tombstone from the replica metadata.

Cleaning up tombstones by using unmanaged code

To use the snapshot technique to clean up tombstones on a filtered replica, perform the following steps:

  1. Project the snapshot knowledge using the current knowledge as the template knowledge. To do this, call ISyncKnowledge2::ProjectOntoKnowledgeWithPrerequisite on the snapshot knowledge, passing the snapshot knowledge for pPrerequisiteKnowledge and the current knowledge of the replica for pTemplateKnowledge. Use the projected knowledge that is returned from this method in the next steps.
  2. Remove tombstones from the replica that are contained in the projected snapshot knowledge.
  3. Combine the forgotten knowledge of the replica with the projected snapshot knowledge and store the result as the new forgotten knowledge of the replica.
  4. Save the current knowledge of the replica as the new snapshot knowledge.

The snapshot technique is recommended because it keeps the knowledge smaller and more efficient. However, the following steps can also be followed to remove a tombstone:

  1. Call IForgottenKnowledge::ForgetToVersion, passing the change version of the tombstone to be removed. If this method succeeds, perform step 2.
  2. Remove the tombstone from the replica metadata.

Custom Filters Cannot Be Used with Change Units

When a custom filter is used by a source provider to enumerate changes that contain change units, unexpected results can occur, including loss of data. Because of this, when a change that contains change units is added to a filtered change batch that uses a custom filter, the ItemChange.AddChangeUnitChange method throws SyncInvalidOperationException exception (for managed code) or ISyncChangeBuilder::AddChangeUnitMetadata returns SYNC_E_INVALID_OPERATION (for unmanaged code).

4. Documentation and Samples