07/10/2009 22:01:58

El documento Notas de la versión describe los cambios importantes y los problemas conocidos que debería leer antes de instalar Microsoft Sync Framework 2.0 o solucionar problemas en la aplicación.

  1. Instalar Sync Framework
    1. Desinstalar la versión preliminar de Sync Framework antes de instalar la versión final
  2. Proveedores de base de datos
    1. Cambios importantes
    2. El comando Compact() puede causar una falta de convergencia de los datos
    3. El aprovisionamiento de bases de datos puede causar errores de serialización
    4. El aprovisionamiento de bases de datos da error en la cuenta de usuario de privilegios mínimos (LUA) de Windows
    5. La aplicación de ejemplo causa una excepción de deserialización
  3. Componentes básicos
    1. Cambios importantes
    2. Algunos métodos pueden devolver errores que no contienen un mensaje de error útil
    3. Las unidades de cambio no se restauran después de un conflicto de eliminación actualización cuando se usan proveedores simples y Filtros de unidades de cambio
    4. Las réplicas filtradas no pueden realizar la enumeración completa de la sincronización de recuperación
    5. La limpieza de marcadores de exclusión de las réplicas filtradas requiere un procesamiento adicional
    6. Los filtros personalizados no se pueden usar con las unidades de cambio
  4. Documentación y ejemplos
    1. Los ejemplos deben ser reconfigurados para ejecutarlos en plataformas que no sean x86
    2. Algunos miembros de API están incorrectamente documentados
    3. Para el chino tradicional, IntelliSense muestra el texto en inglés

1. Instalar Sync Framework

2. Proveedores de base de datos

a. Cambios importantes

Entre Sync Framework 1.0 y Sync Framework 2.0 se han producido los cambios siguientes.

  • Se creó la clase base Microsoft.Synchronization.Data.RelationalSyncProvider para encapsular la lógica que es común a todos los proveedores de bases de datos de Sync Framework. Muchos de los miembros de DbSyncProvider fueron movidos a RelationalSyncProvider, pero la superficie de la API general no cambió significativamente. Microsoft.Synchronization.Data.DbSyncProvider, Microsoft.Synchronization.Data.SqlServer.SqlSyncProvider y Microsoft.Synchronization.Data.SqlServerCe.SqlCeSyncProvider se han heredado de RelationalSyncProvider.
  • Se ha quitado la colección SyncConflict que estaba disponible desde Microsoft.Synchronization.Data.DbSyncTableProgress. Esto mejoró el rendimiento al reducir el uso de memoria para las sesiones de sincronización con un gran número de conflictos. Ahora se recomienda interactuar con los conflictos sobre una base individual utilizando el evento ApplyChangeFailed por cada proveedor.

Entre Sync Framework 2.0 CTP2 y la versión final de Sync Framework 2.0 se han producido los cambios siguientes.

  • Se quitó la propiedad Microsoft.Synchronization.Data.SqlServer.SqlSyncProviderAdapterConfiguration.PkColumnNames. Ahora en su lugar debería usar la propiedad Microsoft.Synchronization.Data.SqlServer.SqlSyncProviderAdapterConfiguration.Columns.
  • Se cambiaron las colecciones siguientes en las colecciones enumerables para que se adhieran a los patrones existentes para los conocidos tipos ADO.Net, como DataSet:
    • Microsoft.Synchronization.Data.DbSyncTableDescription, que está disponible mediante la propiedad Microsoft.Synchronization.Data.DbSyncScopeDescription.Tables.
    • Microsoft.Synchronization.Data.SqlServer.SqlSyncTableProvisioning, que está disponible mediante la propiedad Microsoft.Synchronization.Data.SqlServer.SqlSyncScopeProvisioning.Tables.
    • Microsoft.Synchronization.Data.SqlServerCe.SqlCeSyncTableProvisioning, que está disponible mediante la propiedad Microsoft.Synchronization.Data.SqlServerCe.SqlCeSyncScopeProvisioning.Tables.
  • El método Microsoft.Synchronization.Data.DbSyncColumnDescription.GetInitialParameterName se convirtió a una propiedad para que se conformase a las prácticas recomendadas de diseño de las API. Ahora debe usar en su lugar la propiedad Microsoft.Synchronization.Data.DbSyncColumnDescription.ParameterName.
  • El nombre del método de inicialización de instantánea se cambió a Microsoft.Synchronization.Data.SqlServerCe.SqlCeSyncStoreSnapshotInitialization.InitializeFromSnapshot.

b. El comando Compact() puede causar una falta de convergencia de los datos

c. El aprovisionamiento de bases de datos puede causar errores de serialización

En algunos casos, Sync Framework usa el atributo XmlIgnoreAttribute cuando se aprovisionan las bases de datos. En las versiones más antiguas de .NET Framework, el uso de XmlIgnoreAttribute causa la excepción siguiente:

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

Para evitar este problema, asegúrese de que tiene .NET Framework 2.0 SP1 o una versión posterior instalada en el equipo que está ejecutando el proveedor de bases de datos de Sync Framework.

d. El aprovisionamiento de bases de datos da error en la cuenta de usuario de privilegios mínimos (LUA) de Windows

Si el proceso de sincronización se está ejecutando bajo LUA, se produce el error siguiente cuando intenta aprovisionar una base de datos:

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

Este error se produce porque el serializador que usa Sync Framework necesita acceso de lectura y escritura al directorio temporal de Windows, que LUA no permite.

e. La aplicación de ejemplo causa una excepción de deserialización

Cuando la aplicación de ejemplo intenta configurar el tamaño del lote de sincronización en un valor que no sea cero, se producen las excepciones siguientes:

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

Para arreglar la aplicación de ejemplo, modifique el método GetChangeBatch() en RelationalProviderProxy.cs (line106) para que la creación de instancias del objeto Filestream se haga dentro de la declaración If.

//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. Componentes básicos

a. Cambios importantes

Entre Sync Framework 1.0 y Sync Framework 2.0 se han producido los cambios siguientes.

  • La enumeración Microsoft.Synchronization.FilterType (para código administrado) y la enumeración FILTER_TYPE (para código no administrado) no se usan y se han quitado. Debe quitarse también cualquier referencia a estas enumeraciones que haya en su código.

En el espacio de nombres Microsoft.Synchronization.SimpleProviders se produjeron los siguientes cambios entre Sync Framework 2.0 CTP2 y Sync Framework 2.0 RTM.

  • Se quitaron las siguientes clases y métodos.
    • El constructor AnchorEnumerationContext.
    • El método AnchorEnumerationSimpleSyncProvider.EnumerateItems.
    • El método ISimpleSyncProviderIdGenerator.GenerateNewReplicaId.
    • El método RecoverableErrorReportingContext.RecordRecoverableErrorForChangeUnit.
    • El método SimpleSyncProvider.ChangeReplicaId.
    • La clase ChangeDetectionFailedException.
    • La clase CustomConflictResolutionNotSupportedException.
    • La clase ItemSchemaNotDefinedException.
    • La clase NewItemDoesNotContainAllFieldsException.
    • La clase NoCommonChangeUnitsException.
    • La clase UnknownChangeUnitException.
  • Se cambió el nombre de los métodos siguientes o se cambiaron los parámetros.
    • Se cambió el nombre del método AnchorEnumerationContext.AutodetectDeletes por el de AnchorEnumerationContext.ReportItemsAndAutodetectDeletes y los parámetros del método se cambiaron.
    • Se cambiaron los parámetros del método AnchorEnumerationSimpleSyncProvider.EnumerateChanges.
    • Se cambiaron los parámetros del método ISimpleSyncProviderIdGenerator.GenerateNewItemId.
    • La clase ItemFieldDictionary ya no implementa la interfaz System.Collections.ICollection.
    • Se cambiaron los parámetros del constructor SimpleSyncServices.
    • Se cambió el nombre del método SimpleSyncServices.CleanupTombstones por el de SimpleSyncServices.CleanupDeletedItems.
    • Se cambiaron los parámetros del constructor UnmanagedSimpleSyncProviderWrapper.UnmanagedSimpleSyncProviderWrapper.
    • Se cambiaron los parámetros del método UnmanagedSimpleSyncProviderWrapper.Initialize.
  • Las clases siguientes se movieron desde el espacio de nombres Microsoft.Synchronization.SimpleProviders al espacio de nombres Microsoft.Synchronization.
    • ChangeDeferredByProviderException
    • ChangeReplicaIdPendingException
    • DuplicateItemException
    • ItemNotFoundInMetadataStoreException
    • MetadataStoreVersion2RequiredException
    • OptimisticConcurrencyException
    • RecoverableErrorMustFailEntireItemException
    • SimpleProviderInvalidOperationException
    • SimpleProvidersException

b. Algunos métodos pueden devolver errores que no contienen un mensaje de error útil

Algunos métodos pueden devolver un mensaje de error genérico, como "Exception from HRESULT: 0x80041006", en lugar de una descripción de la causa del error. En la tabla siguiente se enumeran los códigos de error y sus valores. Para las descripciones de estos códigos de error, vea Códigos de error de Sync Framework en la referencia Componentes principales de Sync Framework.

Código de error Valor de código de error

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. Las unidades de cambio no se restauran después de un conflicto de eliminación-actualización cuando se usan proveedores simples y Filtros de unidades de cambio

Esta situación se produce cuando se usan proveedores simples y una de las réplicas de la comunidad de sincronización usa un filtro de unidad de cambio. Los pasos que causan esta situación son los siguientes:

  1. El elemento I es eliminado de la réplica sin filtrar A y, a continuación, se quita el marcador de exclusión.
  2. El elemento I se actualizó en la réplica B. La réplica B usa un filtro de unidad de cambio y, por tanto, no almacena todas las unidades de cambio correspondientes al elemento.
  3. La sincronización se realiza utilizando la réplica B como réplica de origen y la réplica A como la de destino.
  4. Se ha detectado un conflicto eliminación-actualización en el elemento I y se ha resuelto en favor de la actualización de la réplica B. El elemento I se ha restaurado en la réplica A, pero solo contiene los datos correspondientes a las unidades de cambio que se almacenan en la réplica B. La versión de todas las unidades de cambio se ha actualizado a la nueva versión.
  5. La sincronización se realiza de nuevo, esta vez utilizando la réplica C sin filtrar como réplica de origen y la réplica A como la de destino.
  6. Las unidades de cambio perdidas del elemento I no se envían desde la réplica C, porque sus versiones en la réplica A son posteriores a sus versiones en la réplica C.

Para evitar esta situación, actualice las unidades de cambio para el elemento I de la réplica C, para que sus versiones sean posteriores a las versiones de la réplica A y, después, sincronice desde la réplica C a la réplica A.

d. Las réplicas filtradas no pueden realizar la enumeración completa de la sincronización de recuperación

Cuando la réplica de destino está obsoleta y debe realizarse la sincronización de recuperación, la réplica de origen debe ser una réplica sin filtrar para recuperar plenamente la réplica obsoleta. Cuando la réplica de origen es una réplica filtrada, el proveedor de origen no debe realizar una enumeración completa, pues se pueden producir resultados inesperados.

En esta situación, la réplica de origen filtrada puede realizar una sincronización parcial con la réplica de destino obsoleta. Para ello, la aplicación especifica FullEnumerationAction.Partial como respuesta al evento FullEnumerationNeeded (para código administrado) o SFEA_PARTIAL_SYNC como respuesta al método de devolución de llamada ISyncCallback::OnFullEnumerationNeeded (para código no administrado). La aplicación también puede canelar la sincronización especificando FullEnumeration.Abort (para código administrado) o SFEA_ABORT (para código no administrado).

e. La limpieza de marcadores de exclusión de las réplicas filtradas requiere un procesamiento adicional

Cuando una réplica filtrada usa la técnica de instantánea para limpiar los marcadores de exclusión, hay que poner mucho cuidado para asegurarse de que el conocimiento de la réplica contenga siempre el conocimiento olvidado de la réplica. Esto se debe a que pueden darse situaciones en las que el conocimiento de una réplica filtrada es reducido por causa de un elemento que se mueve en relación con el filtro.

Limpiar los marcadores de exclusión mediante código administrado

No use la técnica de instantánea para limpiar marcadores de exclusión en una réplica filtrada. En su lugar, realice los pasos siguientes para quitar un marcador de exclusión:

  1. Llame a ForgottenKnowledge.ForgetTo, pasando el cambio a la versión del marcador de exclusión que se ha de quitar. Si este método se realiza correctamente, realice el paso 2.
  2. Quite el marcador de exclusión desde los metadatos de la réplica.

Limpiar los marcadores de exclusión mediante código no administrado

Para usar la técnica de instantánea para limpiar los marcadores de exclusión en una réplica filtrada, realice los pasos siguientes:

  1. Proyecte el conocimiento de instantánea utilizando el conocimiento actual como el conocimiento de plantilla. Para ello, llame a ISyncKnowledge2::ProjectOntoKnowledgeWithPrerequisite en el conocimiento de instantánea, pasando el conocimiento de instantánea correspondiente a pPrerequisiteKnowledge y el conocimiento actual de la réplica correspondiente a pTemplateKnowledge. Use en los pasos siguientes el conocimiento proyectado que devuelve este método.
  2. Quitar de la réplica los marcadores de exclusión que están contenidos en el conocimiento de instantánea proyectado.
  3. Combinar el conocimiento olvidado de la réplica con el conocimiento de instantánea proyectado y almacenar el resultado como el nuevo conocimiento olvidado de la réplica.
  4. Guardar el conocimiento actual de la réplica como el nuevo conocimiento de instantánea.

Se recomienda la técnica de instantánea porque mantiene un conocimiento más pequeño y eficiente. Sin embargo, también se pueden seguir los pasos siguientes para quitar un marcador de exclusión:

  1. Llame a IForgottenKnowledge::ForgetToVersion, pasando el cambio a la versión del marcador de exclusión que se ha de quitar. Si este método se realiza correctamente, realice el paso 2.
  2. Quite el marcador de exclusión desde los metadatos de la réplica.

Los filtros personalizados no se pueden usar con las unidades de cambio

Cuando un filtro personalizado es usado por un proveedor de origen para enumerar los cambios que contienen las unidades de cambio, se pueden producir resultados inesperados, incluyendo la pérdida de datos. Por ello, cuando un cambio que contiene unidades de cambio se agrega a un lote de cambios filtrado que usa un filtro personalizado, el método ItemChange.AddChangeUnitChange causa una excepción SyncInvalidOperationException (para código administrado) o ISyncChangeBuilder::AddChangeUnitMetadata devuelve SYNC_E_INVALID_OPERATION (para código no administrado).

4. Documentación y ejemplos

a. Los ejemplos deben ser reconfigurados para ejecutarlos en plataformas que no sean x86

Los ejemplos de Sync Framework se configuran para generar en la plataforma x86. Cuando se instala Sync Framework para otra plataforma, como la plataforma x64, los ejemplos dan error al ejecutarse y causan una excepción con el mensaje siguiente: "No se pudo recuperar el generador de clases COM para el componente con CLSID {DBFD020B-D830-4FBE-A927-566B1F57A17A} debido al siguiente error: 80040154".

Para arreglar este problema, reconfigure el ejemplo para generar en la plataforma actual, como la plataforma x64. Vuelva a generar el ejemplo y se ejecutará sin errores.

b. Algunos miembros de API están incorrectamente documentados

  • En la documentación falta una descripción del parámetro filteringType del delegado Microsoft.Synchronization.FilterRequestCallback, del tipo Microsoft.Synchronization.FilteringType. Este parámetro indica el tipo de información incluida en un lote de cambios durante la sincronización filtrada.
  • El valor de retorno de la propiedad Microsoft.Synchronization.Data.DbSyncTableDescription.IsTableMapped se ha descrito incorrectamente en la documentación. Este valor de retorno es false si los valores de la propiedad GlobalName y LocalName son los mismos; en caso contrario es true.

c. Para el chino tradicional, IntelliSense muestra el texto en inglés

Cuando se instala la versión de chino tradicional de Sync Framework 2.0, Microsoft Visual Studio 2008 muestra en inglés el contenido de IntelliSense. Para arreglar este problema, actualícese a Visual Studio 2008 SP1.