Compartilhar via


Tratando conflitos

Durante a sincronização, o provedor de destino recebe um lote de alterações do provedor de origem através do método ProcessChangeBatch (para código gerenciado) ou ProcessChangeBatch (para código não gerenciado). O provedor de destino deverá detectar e tratar quaisquer conflitos que venham a ocorrer devido a essas lista.

Detecção de conflitos

Há duas categorias de conflitos que podem ocorrer na sincronização: conflitos de simultaneidade e de restrição.

Conflitos de simultaneidade

Os conflitos de simultaneidade ocorrem quando a versão de uma alteração da réplica de destino não está contida no conhecimento da réplica de origem. Esses conflitos ocorrem, pois operações de atualização-exclusão e de atualização-atualização afetam o mesmo item que está sendo sincronizado.

Normalmente, o provedor de destino usa um objeto aplicador de alterações fornecido pelo Estrutura de sincronização para detectar conflitos de simultaneidade. O aplicador de alterações é representado pelo objeto NotifyingChangeApplier (para código gerenciado) ou pela interface ISynchronousNotifyingChangeApplier (para código não gerenciado). Para usar um aplicador de alterações para detectar alterações, o provedor de destino deve fornecer informações de versão para cada item no lote de alterações enviado do provedor de origem. Isso pode ser feito das duas maneiras a seguir:

  • O provedor de destino cria uma lista de alterações que corresponde ao lote de alterações enviado pelo provedor de origem. Para cada item no lote de alterações do provedor de origem, o provedor de destino adiciona um item a sua lista que contém a versão deste item na réplica de destino. Esta lista é passada ao aplicador de alterações. O aplicador de alterações a usa para verificar se a versão de destino de cada item está contida no conhecimento da réplica de origem.

  • O provedor de destino não fornece uma lista de versões de destino no aplicador de alterações. Em vez disso, o provedor de destino implementa o método TryGetDestinationVersion (para código gerenciado) ou ISynchronousNotifyingChangeApplierTarget::GetDestinationVersion (para código não gerenciado). Este método será chamado uma vez para cada item no lote de alterações do provedor de origem.

Para entender melhor o que o aplicador de alterações faz para detectar um conflito, considere o cenário no qual um provedor de destino recebe um lote de alterações de um provedor de origem. Para detectar conflitos, as etapas a seguir são executadas para cada item no lote de alterações:

  1. O provedor de destino determina se a versão do item da réplica de destino está contida no conhecimento da réplica de origem.

  2. Se a versão da réplica de destino não está contida no conhecimento da réplica de origem, o objeto será considerado em conflito.

Conflitos de restrição

Os conflitos de restrição são aqueles que violam as restrições postas nos itens, como a relação de pastas ou o local dos dados nomeados identicamente em um sistema de arquivos.

Uma vez que a detecção de um conflito de restrição depende do armazenamento de dados usado por uma réplica, estes tipos de conflitos devem ser detectados pelo provedor. Por exemplo, um provedor que representa um sistema de arquivos hierárquico deve poder detectar restrições específicas do armazenamento que são postas em dados persistentes, como local, nomenclatura, tamanho etc.

Resolução de conflitos

Os conflitos podem ser resolvidos definindo uma diretiva de resolução de conflitos aplicada a todos os conflitos durante a sessão ou tratando um evento que ocorre uma vez para cada conflito.

Definindo uma diretiva de resolução de conflitos

Para especificar uma diretiva que será aplicada a todos os conflitos durante a sessão, um aplicativo especifica uma diretiva de resolução de conflitos na propriedade do provedor de destino ConflictResolutionPolicy (para código gerenciado) ou no método ISyncSession::Start (para código não gerenciado).

Definindo uma ação de resolução de conflitos

Para definir a ação de resolução de conflitos dinamicamente para cada conflito que ocorre, uma aplicativo trata o evento de conflito de item usando o ItemConflicting (para código gerenciado) ou o ISyncCallback::OnConflict (para código não gerenciado). Este evento é acionado somente quando a diretiva de resolução de conflitos está definida como ApplicationDefined (para código gerenciado) ou CRP_NONE (para código não gerenciado).

Código gerenciado Quando o ItemConflicting é gerado, o manipulador de eventos recebe um objeto ItemConflictingEventArgs que contém metadados e dados do item para as duas alterações em conflito. O manipulador de item pode examinar os dois conflitos, fazer as alterações nos metadados ou nos dados do item e definir a ação de resolução para o conflito usando o método SetResolutionAction. O Estrutura de sincronização então processa o conflito e faz as chamadas apropriadas para o provedor de origem ou de destino para aplicar quaisquer alterações.

Código não gerenciado Quando o ISyncCallback::OnConflict é criado, o manipulador de eventos recebe um objeto IChangeConflict que contém metadados e dados do item para as duas alterações em conflito. O manipulador de item pode examinar os dois conflitos, fazer as alterações nos metadados ou nos dados do item e definir a ação de resolução para o conflito usando o método IChangeConflict::SetResolveActionForChange. O Estrutura de sincronização então processa o conflito e faz as chamadas apropriadas para o provedor de origem ou de destino para aplicar quaisquer alterações.

Resoluções de conflitos

O Estrutura de sincronização fornece o seguinte conjunto de ações de resolução de conflitos para as quais trata a maior parte do processamento. Outros tipos de resolução de conflitos podem ser executados trabalhando com as alterações conflitantes diretamente no manipulador de eventos de conflitos de item.

Resolução de conflitos Descrição Disponível como diretiva de sessão ou como ação de item?

Origem ganha

A réplica de origem sempre ganha. Isto suporta uma solução de sincronização somente leitura na qual a réplica de destino não será confiada. O aplicador de alterações passa a alteração para o SaveItemChange (para código gerenciado) ou para o método ISynchronousNotifyingChangeApplierTarget::SaveChange (para código não gerenciado). A alteração é aplicada à réplica de destino exatamente como qualquer alteração não conflitante.

Ambos

Destino ganha

A réplica de destino sempre ganha. Isso suporta o caso no qual a réplica de destino não consume alterações que são feitas por clientes remotos. O aplicador de alterações passa a alteração conflitante para o SaveItemChange (para código gerenciado) ou para o método ISynchronousNotifyingChangeApplierTarget::SaveChange (para código não gerenciado) somente como uma alteração de versão. Somente informações de versão são aplicadas aos metadados na réplica de destino.

Ambos

Mesclar

Mescle as informações de um item em outro. O aplicador de alterações passa a alteração conflitante para o SaveItemChange (para código gerenciado) ou para o método ISynchronousNotifyingChangeApplierTarget::SaveChange (para código não gerenciado) como uma alteração de mesclagem. Os dados do item de origem e de destino são mesclados e o resultado é aplicado à réplica de destino.

Ação de item somente

Registrar em log

Registre conflito em log para tratá-lo depois e não aplique a alteração. O aplicador de alterações passa a alteração conflitante para o método SaveConflict (para código gerenciado) ou ISynchronousNotifyingChangeApplierTarget::SaveConflict (para código não gerenciado).

Ação de item somente

Adiar

Ignore o conflito e não aplique a alteração. O aplicador de alterações não passa a alteração conflitante para o provedor de destino.

Ação de item somente

Conflitos salvos

Quando um conflito é registrado em log, o método SaveConflict (para código gerenciado) ou SaveConflict (para código não gerenciado) é chamado em vez do método SaveItemChange (para código gerenciado) ou SaveChange (para código não gerenciado). Neste caso, o provedor deve salvar o conhecimento de conflito, a alteração conflitante e os dados de conflito. Um aplicativo pode enumerar estes conflitos do log de conflito e pode resolvê-los depois. Lembre-se que este tipo de resolução de conflitos sempre é uma alteração local. Portanto, o aplicativo que está resolvendo conflitos deve aplicar a resolução como uma alteração local, atualizar a contagem em escala e deve adicionar o conhecimento de conflito ao conhecimento local.

Além disso, um aplicativo que está resolvendo conflitos salvos deve tratar conflitos obsoletos. Em particular, quando um provedor registra em log um conflito novo, este deve verificar o conflito novo com seu conhecimento para garantir que o conflito que está sendo registrado em log substitui quaisquer conflitos previamente registrados em log para aquele item. Conflitos obsoletos também devem ser limpos do log. Um aplicativo pode limpar conflitos obsoletos de forma assíncrona em vez de no provedor. Neste caso, o aplicativo deve verificar que conflitos não estão obsoletos antes de tentar resolvê-los.

Reduzindo conflitos usando unidades de alteração

O número de conflitos pode ser reduzido usando unidades de alterações para representar alterações de subitem. Quando são usadas unidades de alteração, as versões são rastreadas para unidades de alterações em vez de para o item como um todo. Portanto, alterações que são feitas para unidades de alterações diferentes dentro do mesmo item não resultará em um conflito. Para obter mais informações, consulte Sincronizando unidades de alteração.

Consulte também

Referência

Interface ISyncKnowledge
Interface ISyncProvider
IKnowledgeSyncProvider Interface
IKnowledgeSyncProvider::ProcessChangeBatch
Interface ISynchronousNotifyingChangeApplierTarget
Interface IAsynchronousNotifyingChangeApplierTarget
ISyncCallback::OnConflict
Enumeração CONFLICT_RESOLUTION_POLICY
Enumeração SYNC_RESOLVE_ACTION
SyncKnowledge
KnowledgeSyncProvider
INotifyingChangeApplierTarget
ItemConflicting
ConflictResolutionPolicy
ConflictResolutionAction

Conceitos

Provedores de sincronização
Aplicando alterações
Noções básicas sobre conhecimento de sincronização