Detectar y resolver conflictos de simultaneidad
Los conflictos de simultaneidad se producen cuando el mismo elemento o unidad de cambio se modifica en dos réplicas diferentes que se sincronizan más tarde. Sync Framework proporciona un objeto aplicador de cambios que simplifica la detección y resolución de conflictos de simultaneidad.
Cómo detecta y resuelve el aplicador de cambios los conflictos de simultaneidad
Un conflicto de simultaneidad se detecta cuando la versión de la réplica de destino no está incluida en el conocimiento de la réplica de origen.
Sync Framework proporciona un objeto aplicador de cambios que puede utilizar el proveedor de destino para detectar los conflictos de simultaneidad. El aplicador de cambios detecta los conflictos de simultaneidad realizando los pasos siguientes para cada elemento en el lote de cambios que envía el proveedor de origen:
Determina si la versión de la réplica de destino del elemento está incluida en el conocimiento de la réplica de origen.
Si la versión de la réplica de destino del elemento no está incluida en el conocimiento de la réplica de origen, el cambio está en conflicto.
Después de que el aplicador de cambios detecta un conflicto de simultaneidad, resuelve el conflicto según la directiva de resolución de conflictos establecida para la sesión o según la acción de resolución de conflictos que haya establecido la aplicación para el conflicto especificado.
Detectar conflictos de simultaneidad mediante un aplicador de cambios
Para utilizar un aplicador de cambios con el fin de detectar los cambios, el proveedor de destino crea en primer lugar el objeto aplicador de cambios.
Código administrado Cree un objeto NotifyingChangeApplier.
Código no administrado Cree un objeto ISynchronousNotifyingChangeApplier; para ello, pase IID_ISynchronousNotifyingChangeApplier al método IProviderSyncServices::CreateChangeApplier.
El siguiente proveedor de destino debe proporcionar información sobre la versión para cada elemento en el lote de cambios que envíe el proveedor de origen. Hay dos maneras de hacerlo:
El proveedor de destino genera una lista de versiones que corresponde al lote de cambios que el proveedor de origen envía. El aplicador de cambios usa la lista para determinar si la versión de destino de un elemento está incluida en el conocimiento de la réplica de origen.
Código administrado Para crear esta lista, cree un objeto de tipo System.Collections.Generic.IEnumerable<Microsoft.Synchronization.ItemChange>. Para cada elemento del lote de cambios del proveedor de origen, agregue un elemento a esta lista que contenga la versión de la réplica de destino del elemento. Pase esta lista al aplicador de cambios como el parámetro destinationVersions de la sobrecarga del método adecuada, como por ejemplo, ApplyChanges.
Código no administrado Para crear esta lista, cree un objeto IDestinationChangeVersionsBuilder llamando a IProviderSyncServices::CreateDestinationChangeVersionsBuilder. Para cada elemento del lote de cambios del proveedor de origen, agregue un elemento a esta lista que contenga la versión de la réplica de destino del elemento, para lo cual llame a IDestinationChangeVersionsBuilder::AddItemMetadata. Obtenga un enumerador para la lista llamando a IDestinationChangeVersionsBuilder::GetChangeEnumerator y pase el enumerador al aplicador de cambios como el parámetro pDestinationVersions del método ApplyChanges.
Otra alternativa es que el proveedor de destino no pase una lista de las versiones de destino al aplicador de cambios. En su lugar, el proveedor de destino implementa el método TryGetDestinationVersion (para el código administrado) o el método ISynchronousNotifyingChangeApplierTarget::GetDestinationVersion (para el código no administrado). El aplicador de cambios llama a este método una vez para cada elemento del lote de cambios del proveedor de origen. En este método, el proveedor de destino busca la versión de la réplica de destino del elemento y la devuelve al aplicador de cambios, de forma que este pueda determinar si el cambio es un conflicto.
Finalmente, el proveedor de destino llama al método ISynchronousNotifyingChangeApplier::ApplyChanges (para código administrado) o al método ApplyChanges (para código no administrado) del aplicador de cambios.
Utilizar un aplicador de cambios para resolver conflictos de simultaneidad
El aplicador de cambios ayuda a un proveedor de destino a resolver los conflictos enviando llamadas a un objeto de destino del aplicador de cambios que especifica el proveedor. Cuando se especifica una directiva de resolución de conflictos, el aplicador de cambios la utiliza para determinar la acción de resolución de conflictos correcta con el fin de resolver los conflictos que se produzcan. Cuando se especifica una resolución de conflictos personalizada, el aplicador de cambios informa a la aplicación de sincronización del conflicto y la aplicación especifica la acción de resolución de conflictos. En cualquiera de las situaciones, el aplicador de cambios llama al método de destino del aplicador de cambios apropiado y el objeto de destino del aplicador de cambios emprende la acción; como por ejemplo, guardar el cambio en la réplica o registrar el conflicto para su procesamiento ulterior.
Por lo general, la aplicación de sincronización determina una directiva de resolución de conflictos de simultaneidad antes de que se inicie la sincronización.
Código administrado La aplicación determina la directiva estableciendo la propiedad ConflictResolutionPolicy del proveedor de destino en el valor deseado.
Código no administrado La aplicación determina la directiva en el parámetro resolutionPolicy del método ISyncSession::Start. El proveedor de destino recibe esta directiva como el parámetro resolutionPolicy del método IKnowledgeSyncProvider::ProcessChangeBatch.
El proveedor de destino pasa la directiva de resolución de conflictos al aplicador de cambios, de forma que este pueda enviar métodos adecuadamente al destino del aplicador de cambios. El destino del aplicador de cambios se representa mediante el objeto INotifyingChangeApplierTarget (para código administrado) o el objeto ISynchronousNotifyingChangeApplierTarget (para código no administrado).
Sync Framework define las directivas de resolución de conflictos de simultaneidad siguientes.
Directiva de resolución de conflictos | Descripción |
---|---|
SourceWins (para código administrado), CRP_SOURCE_PROVIDER_WINS (para código no administrado) |
El cambio realizado en la réplica de origen siempre gana. Esto admite una solución de sincronización de solo lectura donde la réplica de destino no es de confianza. Sync Framework determina una acción de resolución de conflictos de SourceWins (para código administrado) o SRA_ACCEPT_SOURCE_PROVIDER (para código no administrado). |
DestinationWins (para código administrado), CRP_DESTINATION_PROVIDER_WINS (para código no administrado) |
El cambio realizado en la réplica de destino siempre gana. Este sistema admite el caso en el que la réplica de destino no consume los cambios que los clientes remotos realizan. Sync Framework determina una acción de resolución de conflictos de DestinationWins (para código administrado) o SRA_ACCEPT_DESTINATION_PROVIDER (para código no administrado). |
ApplicationDefined (para código administrado), CRP_NONE (para código no administrado) |
El aplicador de cambios informa a la aplicación de sincronización de cada conflicto según se van produciendo, mediante el evento ItemConflicting (para código administrado) o el método ISyncCallback::OnConflict (para código no administrado). La aplicación examina los elementos conflictivos y determina la acción de resolución de conflictos llamando a SetResolutionAction (para código administrado), a IChangeConflict::SetResolveActionForChange o a IChangeConflict::SetResolveActionForChangeUnit (para código no administrado). |
Determinar resoluciones de conflictos personalizadas
Para determinar la acción de resolución de conflictos de forma dinámica para cada conflicto de simultaneidad que se produce, una aplicación emprende las siguientes acciones antes de iniciar la sincronización.
Código administrado
Registra un controlador de eventos para el evento ItemConflicting del proveedor de destino.
Establece la propiedad ConflictResolutionPolicy del proveedor de destino en ApplicationDefined.
Código no administrado
Implementa el método ISyncCallback::OnConflict y registra el objeto ISyncCallback llamando a ISyncSession::RegisterCallback.
Pasa CRP_NONE para el parámetro resolutionPolicy de ISyncSession::Start.
Durante la sincronización, el aplicador de cambios genera el evento ItemConflicting (para código administrado) o el método ISyncCallback::OnConflict (para código no administrado), una vez para cada conflicto de simultaneidad que detecta. La aplicación puede examinar los dos cambios en conflicto, realizar cambios en los metadatos, o en los datos del elemento, y establecer la acción de resolución para el conflicto mediante el método SetResolutionAction (para código administrado), o bien el método IChangeConflict::SetResolveActionForChange o IChangeConflict::SetResolveActionForChangeUnit (para código no administrado). A continuación, el aplicador de cambios procesa el conflicto y envía la llamada adecuada al objeto de destino del aplicador de cambios.
Nota
La misma acción de resolución de conflictos se debe especificar para todas las unidades de cambio en conflicto en un elemento; de lo contrario, pueden producirse resultados inesperados. Cuando se requiera este tipo de resolución de conflictos, especifique que el conflicto se resuelva mediante combinación y administre la resolución en el proveedor de destino.
Acciones de resolución de conflictos de simultaneidad que utiliza el código administrado
Sync Framework proporciona el siguiente conjunto de acciones de resolución de conflictos de simultaneidad para las que el aplicador de cambios se ocupa de la mayor parte del procesamiento.
Acción de resolución de conflictos | Descripción |
---|---|
SourceWins |
El cambio realizado en la réplica de origen gana. El aplicador de cambios pasa el cambio a SaveChangeWithChangeUnits o al método SaveItemChange, y especifica una acción de almacenamiento de UpdateVersionAndData. El cambio se aplica en la réplica de destino exactamente igual que cualquier cambio que no esté en conflicto. |
DestinationWins |
El cambio realizado en la réplica de destino gana. El aplicador de cambios pasa un cambio sólo para versiones a SaveChangeWithChangeUnits o al método SaveItemChange, y especifica una acción de almacenamiento de UpdateVersionOnly. Solo se actualiza la información relativa a la versión del elemento en los metadatos en la réplica de destino. No se realizan cambios en los datos del elemento. |
Combina los datos del elemento de origen en el elemento de destino. El aplicador de cambios pasa los datos del cambio de la réplica de origen a SaveChangeWithChangeUnits o al método SaveItemChange, y especifica una acción de almacenamiento de UpdateVersionAndMergeData. El proveedor de destino combina los datos de elemento de origen y los datos de elemento de destino, y se aplica el resultado a la réplica de destino. |
|
Registra el conflicto y no aplica el cambio. El aplicador de cambios pasa los datos del conflicto al método SaveConflict, que guarda el conflicto en un registro de conflictos. Para obtener más información sobre el registro de conflictos, vea Registrar y administrar conflictos. |
|
Omita el conflicto y no aplique el cambio. El aplicador de cambios no pasa los datos del conflicto al proveedor de destino. |
|
El último escritor gana |
El cambio más reciente gana. La aplicación recupera la hora en la que se realizó el cambio en la réplica de origen y la hora en la que se realizó el cambio en la réplica de destino, para lo que llama a GetItemChangeTime o GetChangeUnitChangeTime en los dos cambios. La aplicación compara las dos horas y determina la acción de resolución de conflictos que aplica el último cambio. Por ejemplo, si se realiza en último lugar el cambio de destino, la aplicación determina una acción de resolución de conflictos de DestinationWins. |
Acciones de resolución de conflictos de simultaneidad que utiliza el código no administrado
Sync Framework proporciona el siguiente conjunto de acciones de resolución de conflictos de simultaneidad para las que el aplicador de cambios se ocupa de la mayor parte del procesamiento.
Acción de resolución de conflictos | Descripción |
---|---|
SRA_ACCEPT_SOURCE_PROVIDER |
El cambio realizado en la réplica de origen gana. El aplicador de cambios pasa el cambio a ISynchronousNotifyingChangeApplierTarget::SaveChangeWithChangeUnits o al método ISynchronousNotifyingChangeApplierTarget::SaveChange, y especifica una acción de almacenamiento de SSA_UPDATE_VERSION_AND_DATA. El cambio se aplica en la réplica de destino exactamente igual que cualquier cambio que no esté en conflicto. |
SRA_ACCEPT_DESTINATION_PROVIDER |
El cambio realizado en la réplica de destino gana. El aplicador de cambios pasa un cambio solo para versiones a SaveChangeWithChangeUnits o al método SaveChange, y especifica una acción de almacenamiento de SSA_UPDATE_VERSION_ONLY. Solo se actualiza la información relativa a la versión del elemento en los metadatos en la réplica de destino. No se realizan cambios en los datos del elemento. |
SRA_MERGE |
Combina los datos del elemento de origen en el elemento de destino. El aplicador de cambios pasa los datos del cambio de la réplica de origen al método SaveChange o SaveChangeWithChangeUnits, y especifica una acción de almacenamiento de SSA_UPDATE_VERSION_AND_MERGE_DATA. El proveedor de destino combina los datos de elemento de origen y los datos de elemento de destino, y se aplica el resultado a la réplica de destino. |
SRA_TRANSFER_AND_DEFER |
Registra el conflicto y no aplica el cambio. El aplicador de cambios pasa los datos del conflicto al método ISynchronousNotifyingChangeApplierTarget::SaveConflict, que guarda el conflicto en un registro de conflictos. Para obtener más información sobre el registro de conflictos, vea Registrar y administrar conflictos. |
SRA_DEFER |
Omita el conflicto y no aplique el cambio. El aplicador de cambios no pasa los datos del conflicto al proveedor de destino. |
El último escritor gana |
El cambio más reciente gana. La aplicación recupera la hora en la que se realizó el cambio en la réplica de origen y la hora en la que se realizó el cambio en la réplica de destino, para lo que llama a ISupportLastWriteTime::GetItemChangeTime o ISupportLastWriteTime::GetChangeUnitChangeTime en los dos cambios. La aplicación compara las dos horas y determina la acción de resolución de conflictos que aplica el último cambio. Por ejemplo, si el cambio de destino se realiza en último lugar, la aplicación determina una acción de resolución de conflictos de SRA_ACCEPT_DESTINATION_PROVIDER. |
Vea también
Referencia
Interfaz ISynchronousNotifyingChangeApplier
Interfaz ISynchronousNotifyingChangeApplierTarget
Enumeración CONFLICT_RESOLUTION_POLICY
Enumeración SYNC_RESOLVE_ACTION
NotifyingChangeApplier
INotifyingChangeApplierTarget
ConflictResolutionAction
ConflictResolutionPolicy
Conceptos
Controlar los conflictos
Detectar y resolver conflictos de restricción