Detectando e solucionando conflitos de simultaneidade
Os conflitos de simultaneidade ocorrem quando o mesmo item ou a mesma unidade de alteração é modificada em duas réplicas diferentes que são sincronizadas posteriormente. O Sync Framework fornece um objeto de aplicador de alterações que simplifica a detecção e a resolução de conflitos de simultaneidade.
Como o aplicador de alterações detecta e resolve conflitos de simultaneidade
Um conflito de simultaneidade é detectado quando a versão de uma alteração da réplica de destino não está contida no conhecimento da réplica de origem.
O Sync Framework fornece um objeto aplicador de alterações que o provedor de destino pode usar para detectar os conflitos de simultaneidade. O aplicador de alterações detecta os conflitos de simultaneidade executando as seguintes etapas para cada item no lote de alterações enviado pelo provedor de origem:
Determina se a versão do item da réplica de destino está contida no conhecimento da réplica de origem.
Se a versão do item da réplica de destino não estiver contida no conhecimento da réplica de origem, a alteração estará em conflito.
Ao detectar um conflito de simultaneidade, o aplicador de alterações resolve o conflito de acordo com a política de resolução de conflitos definida para a sessão, ou de acordo com a ação de resolução de conflitos definida pelo aplicativo para o conflito especificado.
Detectando conflitos de simultaneidade usando um aplicador de alterações
Para usar um aplicador de alterações para detectar alterações, o provedor de destino primeiro cria o objeto aplicador de alterações.
Código gerenciado Criar um objeto NotifyingChangeApplier.
Código não gerenciado Criar um objeto ISynchronousNotifyingChangeApplier passando IID_ISynchronousNotifyingChangeApplier para o método IProviderSyncServices::CreateChangeApplier.
Em seguida, o provedor de destino deve fornecer informações de versão de cada item do lote de alterações enviado pelo provedor de origem. Isso pode ser feito das duas maneiras a seguir:
O provedor de destino cria uma lista de versões correspondente ao lote de alterações enviadas pelo provedor de origem. O aplicador de alterações usa essa lista para determinar se a versão de destino de um item está contida no conhecimento da réplica de origem.
Código gerenciado Para criar essa lista, crie um objeto do tipo System.Collections.Generic.IEnumerable<Microsoft.Synchronization.ItemChange>. Para cada item do lote de alterações do provedor de origem, adicione a essa lista um item que contenha a versão do item da réplica de destino. Passe essa lista para o aplicador de alterações como o parâmetro destinationVersions da sobrecarga do método apropriado, como ApplyChanges.
Código não gerenciado Para criar essa lista, crie um objeto IDestinationChangeVersionsBuilder chamando IProviderSyncServices::CreateDestinationChangeVersionsBuilder. Para cada item do lote de alterações do provedor de origem, adicione a essa lista um item que contenha a versão do item da réplica de destino chamando IDestinationChangeVersionsBuilder::AddItemMetadata. Obtenha um enumerador para a lista chamando IDestinationChangeVersionsBuilder::GetChangeEnumerator e passe o enumerador para o aplicador de alterações como o parâmetro pDestinationVersions do método ApplyChanges.
Como alternativa, o provedor de destino não passa uma lista de versões de destino para o 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). O aplicador de alterações chama esse método uma vez para cada item no lote de alterações do provedor de origem. Nesse método, o provedor de destino procura a versão do item da réplica de destino e a retorna para o aplicador de alterações, para que este possa determinar se a alteração está em conflito.
Finalmente, o provedor de destino chama o método ApplyChanges (para código gerenciado) ou ISynchronousNotifyingChangeApplier::ApplyChanges (para código não gerenciado) do aplicador de alterações.
Usando um aplicador de alterações para resolver conflitos de simultaneidade
O aplicador de alterações ajuda um provedor de destino a resolver conflitos despachando chamadas para o objeto de destino de um aplicador de alterações especificado pelo provedor. Quando uma política de resolução de conflitos é especificada, o aplicador de alterações a utiliza para determinar a ação correta de resolução de conflitos a ser executada para resolver cada conflito que ocorrer. Quando a resolução de conflitos personalizada é especificada, o aplicador de alterações notifica o conflito ao aplicativo de sincronização, e este especifica a ação de resolução de conflitos. Em qualquer situação, o aplicador de alterações chama o método de destino apropriado do aplicador de alterações e o objeto de destino do aplicador de alterações executa a ação. Por exemplo, salvar a alteração da réplica ou registrar em log o conflito para processamento posterior.
O aplicativo de sincronização geralmente especifica uma política de resolução de conflitos de simultaneidade antes do início da sincronização.
Código gerenciado O aplicativo especifica a política definindo a propriedade ConflictResolutionPolicy do provedor de destino com o valor desejado.
Código não gerenciado O aplicativo especifica a política no parâmetro resolutionPolicy do método ISyncSession::Start. O provedor de destino recebe essa política como o parâmetro resolutionPolicy do método IKnowledgeSyncProvider::ProcessChangeBatch.
O provedor de destino passa a política de resolução de conflitos para o aplicador de alterações para que este possa despachar métodos corretamente para o destino do aplicador de alterações. O destino do aplicador de alterações é representado pelo objeto INotifyingChangeApplierTarget (para código gerenciado) ou ISynchronousNotifyingChangeApplierTarget (para código não gerenciado)
O Sync Framework define as políticas de resolução de conflitos de simultaneidade a seguir.
Política de resolução de conflitos | Descrição |
---|---|
SourceWins (para código gerenciado), CRP_SOURCE_PROVIDER_WINS (para código não gerenciado) |
A alteração feita na réplica de origem sempre vence. Isso dá suporte a uma solução de sincronização somente leitura na qual na réplica de destino não deve ser confiável. O Sync Framework especifica uma ação de resolução de conflitos SourceWins (para código gerenciado) ou SRA_ACCEPT_SOURCE_PROVIDER (para código não gerenciado). |
DestinationWins (para código gerenciado), CRP_DESTINATION_PROVIDER_WINS (para código não gerenciado) |
A alteração feita na réplica de destino sempre vence. Isso dá suporte ao caso no qual a réplica de destino não consome alterações feitas por clientes remotos. O Sync Framework especifica uma ação de resolução de conflitos DestinationWins (para código gerenciado) ou SRA_ACCEPT_DESTINATION_PROVIDER (para código não gerenciado). |
ApplicationDefined (para código gerenciado), CRP_NONE (para código não gerenciado) |
O aplicador de alterações notifica cada conflito ao aplicativo de sincronização, à medida que eles ocorrem, usando o evento ItemConflicting (para código gerenciado) ou o método ISyncCallback::OnConflict (para código não gerenciado). O aplicativo examina os itens conflitantes e especifica a ação de resolução de conflitos chamando SetResolutionAction (para código gerenciado), ou IChangeConflict::SetResolveActionForChange ou IChangeConflict::SetResolveActionForChangeUnit (para código não gerenciado). |
Especificando resoluções de conflitos personalizadas
Para especificar a ação de resolução de conflitos dinamicamente para cada conflito de simultaneidade que ocorre, um aplicativo executa as ações a seguir antes de iniciar a sincronização.
Código gerenciado
Registra um manipulador de eventos para o evento ItemConflicting do provedor de destino.
Define a propriedade ConflictResolutionPolicy do provedor de destino como ApplicationDefined.
Código não gerenciado
Implementa o método ISyncCallback::OnConflict e registra o objeto ISyncCallback chamando ISyncSession::RegisterCallback.
Passa CRP_NONE para o parâmetro resolutionPolicy ISyncSession::Start.
Durante a sincronização, o aplicador de alterações gera o evento ItemConflicting (para código gerenciado) ou o método ISyncCallback::OnConflict (para código não gerenciado) uma vez para cada conflito de simultaneidade que ele detectar. O aplicativo pode examinar as duas alterações em conflito, fazer alterações nos metadados ou nos dados do item e definir a ação de resolução do conflito usando o método SetResolutionAction (para código gerenciado), ou o método IChangeConflict::SetResolveActionForChange ou IChangeConflict::SetResolveActionForChangeUnit (para código não gerenciado). O aplicador de alterações processa o conflito e distribui a chamada apropriada para o objeto de destino do aplicador de alterações.
Dica
A mesma ação de resolução de conflitos deve ser especificada para todas as unidades de alteração conflitantes em um item; caso contrário, poderão ocorrer resultados inesperados. Quando esse tipo de resolução de conflitos for exigido, especifique que o conflito seja resolvido por mesclagem e manipule a resolução no provedor de destino.
Ações de resolução de conflitos de simultaneidade usadas pelo código gerenciado
O Sync Framework fornece o conjunto de ações de resolução de conflitos de simultaneidade a seguir, para as quais o aplicador de alterações manipula a maior parte do processamento.
Ação de resolução de conflitos | Descrição |
---|---|
SourceWins |
A alteração feita na réplica de origem vence. O aplicador de alterações passa a alteração para o método SaveItemChange ou SaveChangeWithChangeUnits e especifica uma ação de salvamento UpdateVersionAndData. A alteração é aplicada à réplica de destino exatamente como qualquer alteração não conflitante. |
DestinationWins |
A alteração feita na réplica de destino vence. O aplicador de alterações passa uma alteração somente de versão para o método SaveItemChange ou SaveChangeWithChangeUnits e especifica uma ação de salvamento UpdateVersionOnly. Somente as informações de versão do item são atualizadas nos metadados na réplica de destino. Nenhuma alteração de dados de item é feita. |
Mescle os dados do item de origem no item de destino. O aplicador de alterações passa os dados de alteração da réplica de origem para o método SaveItemChange ou SaveChangeWithChangeUnits e especifica uma ação de salvamento UpdateVersionAndMergeData. O provedor de destino combina os dados do item de origem e os dados do item de destino e aplica o resultado à réplica de destino. |
|
Registre o conflito em log e não aplique a alteração. O aplicador de alterações passa os dados do conflito para o método SaveConflict, o qual salva o conflito em um log de conflitos. Para obter mais informações sobre como registrar os conflitos em log, consulte Registrando em log e gerenciando conflitos. |
|
Ignore o conflito e não aplique a alteração. O aplicador de alterações não passa os dados do conflito para o provedor de destino. |
|
O último gravador vence |
A alteração feita mais recentemente vence. O aplicativo recupera a hora em que a alteração foi feita na réplica de origem e a hora em que a alteração foi feita na réplica de destino chamando GetItemChangeTime ou GetChangeUnitChangeTime nas duas alterações. O aplicativo compara os dois horários e especifica a ação de resolução de conflitos que aplica a alteração que foi feita por último. Por exemplo, quando a alteração de destino foi feita por último, o aplicativo especifica uma ação de resolução de conflitos DestinationWins. |
Ações de resolução de conflitos de simultaneidade usadas pelo código não gerenciado
O Sync Framework fornece o conjunto de ações de resolução de conflitos de simultaneidade a seguir, para as quais o aplicador de alterações manipula a maior parte do processamento.
Ação de resolução de conflitos | Descrição |
---|---|
SRA_ACCEPT_SOURCE_PROVIDER |
A alteração feita na réplica de origem vence. O aplicador de alterações passa a alteração para o método ISynchronousNotifyingChangeApplierTarget::SaveChange ou ISynchronousNotifyingChangeApplierTarget::SaveChangeWithChangeUnits e especifica uma ação de salvamento SSA_UPDATE_VERSION_AND_DATA. A alteração é aplicada à réplica de destino exatamente como qualquer alteração não conflitante. |
SRA_ACCEPT_DESTINATION_PROVIDER |
A alteração feita na réplica de destino vence. O aplicador de alterações passa uma alteração somente de versão para o método SaveChange ou SaveChangeWithChangeUnits e especifica uma ação de salvamento SSA_UPDATE_VERSION_ONLY. Somente as informações de versão do item são atualizadas nos metadados na réplica de destino. Nenhuma alteração de dados de item é feita. |
SRA_MERGE |
Mescle os dados do item de origem no item de destino. O aplicador de alterações passa os dados de alteração da réplica de origem para o método SaveChange ou SaveChangeWithChangeUnits e especifica uma ação de salvamento SSA_UPDATE_VERSION_AND_MERGE_DATA. O provedor de destino combina os dados do item de origem e os dados do item de destino e aplica o resultado à réplica de destino. |
SRA_TRANSFER_AND_DEFER |
Registre o conflito em log e não aplique a alteração. O aplicador de alterações passa os dados do conflito para o método ISynchronousNotifyingChangeApplierTarget::SaveConflict, o qual salva o conflito em um log de conflitos. Para obter mais informações sobre como registrar os conflitos em log, consulte Registrando em log e gerenciando conflitos. |
SRA_DEFER |
Ignore o conflito e não aplique a alteração. O aplicador de alterações não passa os dados do conflito para o provedor de destino. |
O último gravador vence |
A alteração feita mais recentemente vence. O aplicativo recupera a hora em que a alteração foi feita na réplica de origem e a hora em que a alteração foi feita na réplica de destino chamando ISupportLastWriteTime::GetItemChangeTime ou ISupportLastWriteTime::GetChangeUnitChangeTime nas duas alterações. O aplicativo compara os dois horários e especifica a ação de resolução de conflitos que aplica a alteração que foi feita por último. Por exemplo, quando a alteração de destino foi feita por último, o aplicativo especifica uma ação de resolução de conflitos SRA_ACCEPT_DESTINATION_PROVIDER. |
Consulte também
Referência
Interface ISynchronousNotifyingChangeApplier
Interface ISynchronousNotifyingChangeApplierTarget
Enumeração CONFLICT_RESOLUTION_POLICY
Enumeração SYNC_RESOLVE_ACTION
NotifyingChangeApplier
INotifyingChangeApplierTarget
ConflictResolutionAction
ConflictResolutionPolicy
Conceitos
Manipulando conflitos
Detectando e solucionando conflitos de restrição