Compartilhar via


Manipulando conflitos para provedores simples

Se for possível, crie aplicativos de modo a evitar conflitos. A detecção e a solução de conflitos representam complexidade, processamento e tráfego de rede adicionais. Em alguns aplicativos, os conflitos não podem ser evitados. Por exemplo, em um aplicativo de força de vendas, dois vendedores podem dividir um território. Os dois podem atualizar os dados para o mesmo cliente e as mesmas ordens. Para assegurar que as alterações feitas em itens na comunidade de sincronização sejam propagadas corretamente, o provedor de destino deverá detectar e manipular conflitos que ocorrem entre itens enviados do provedor de origem e itens na réplica de destino. O Sync Framework fornece objetos que executam a maior parte do trabalho necessário para detectar e tratar conflitos.

O Sync Framework detecta conflitos no nível do item ou da unidade de alteração. O Sync Framework reconhece duas categorias de conflitos que podem ocorrer durante a sincronização: conflitos de simultaneidade e conflitos de restrição. Os conflitos de simultaneidade ocorrem quando o mesmo item ou a mesma unidade de alteração é alterada em duas réplicas diferentes que são sincronizadas posteriormente. Os conflitos de restrição são aqueles que violam as restrições aplicadas a itens ou unidades de alteração, como o relação de pastas ou o local de dados com nomes idênticos em um sistema de arquivos. O Sync Framework divide conflitos de restrição nos três seguintes tipos.

  • Um conflito de colisão ocorre quando o item não pode ser salvo porque está em conflito com outro item no repositório de destino. Por exemplo, quando o provedor de origem envia um arquivo com os mesmos nome e local de um arquivo existente na réplica de destino.

  • Um conflito de pai ausente ocorre quando um item não pode ser salvo em um repositório de dados hierárquico porque ele requer um item pai que não existe. Por exemplo, quando o provedor de origem envia um arquivo a ser salvo em um diretório que não existe na réplica de destino.

  • Outros conflitos de restrição ocorrem quando o item a ser salvo viola uma restrição da réplica de destino. Por exemplo, quando o provedor de origem envia um arquivo muito grande para ser salvo na réplica de destino ou quando a alteração viola alguma lógica de negócios na réplica de destino.

As restrições estão relacionadas aos recursos específicos de um repositório de itens, como restrições de chave estrangeira que são comuns em bancos de dados. Os provedores simples só oferecem suporte para conflitos de restrição de colisão. Para obter mais informações sobre como manipular conflitos para provedores personalizados padrão, consulte Detectando e solucionando conflitos de restrição.

Noções básicas sobre manipulação de conflitos

Para decidir como manipular conflitos de simultaneidade e conflitos de restrição, você deve responder a duas perguntas importantes:

  • Os conflitos devem ser resolvidos automaticamente durante a sincronização ou o aplicativo deve ser notificado quando um conflito é detectado para que possa acionar a resolução de conflitos?

  • Todos os conflitos devem ser resolvidos por meio da especificação de que a origem ou o destino prevaleçam ou é necessária uma manipulação de conflitos mais sofisticada? Por exemplo, em um conflito de simultaneidade, convém mesclar os dados de origem e destino em um único item aplicado a ambas as réplicas.

Depois de responder a essas perguntas, você pode especificar como o Sync Framework deve se comportar quando encontrar um conflito:

  1. Especifique uma política de resolução para conflitos de simultaneidade e conflitos de restrição de colisão. A política determina se o Sync Framework resolve automaticamente o conflito ou se o aplicativo assume como padrão a resposta a um evento para manipular o conflito.

    Se você especificar uma política diferente da padrão, o Sync Framework definirá a ação de resolução de conflito apropriada quando um conflito ocorrer. Por exemplo, se você especificar uma política do tipo "origem prevalece" para conflitos de simultaneidade, a ação "origem prevalece" será definida se um conflito desse tipo for detectado durante uma sessão de sincronização. Se você aceitar o padrão para uma ou para ambas as políticas de resolução, o provedor ou o aplicativo deverá responder aos eventos acionados quando um conflito é detectado. O provedor pode responder com a implementação dos seguintes métodos:

    Se o provedor não implementar esses métodos, os seguintes retornos de chamada de aplicativo serão usados para que o aplicativo possa definir a ação de resolução. Se o aplicativo não responder a esses eventos, a resolução dos conflito será adiada até uma sessão de sincronização subsequente. Nessa situação, o conflito nunca será resolvido, a menos que os dados conflitantes ou o aplicativo seja alterado.

    Em resposta ao conflito, o provedor ou o aplicativo deve definir uma ação de resolução.

    Além de configurar a ação de resolução, você também pode incluir código personalizado no manipulador de eventos. Por exemplo, você pode exibir itens conflitantes em uma interface do usuário quando eles são processados.

  2. Para algumas ações de resolução que o Sync Framework ou o aplicativo define, você deve implementar um das seguintes interfaces ou ambas:

    Para conflitos de simultaneidade, os métodos de resolução implementados para essas interfaces são diferenciados pelo tipo de conflitos aos quais respondem, como um conflito de atualização/atualização. Para conflitos de restrição, os métodos de resolução implementados são diferenciados pelo resultado da resolução. Por exemplo, renomear o item de origem.

    Para conflitos de simultaneidade, se a ação for definida como Merge (para código gerenciado) ou SRA_MERGE (para código não gerenciado), você deverá implementar os seguintes métodos que manipulam os três tipos de conflitos de simultaneidade:

    A implementação deve mesclar os itens conflitantes de um modo apropriado para a réplica e o aplicativo, contanto que um item final represente os dois itens conflitantes.

    Para conflitos de restrição de colisão, implemente métodos baseados nas ações que podem ser definidas:

Exemplo de código gerenciado

Neste exemplo, as políticas para manipular conflitos relacionadas a conflitos de simultaneidade e conflitos de restrição são mantidas como o padrão ApplicationDefined. Isso significa que o aplicativo registrará os eventos ItemConflicting e ItemConstraint e especificará uma ação para resolver conflitos se eles ocorrerem durante o processamento da sincronização. O exemplo de código a seguir mostra os manipuladores de eventos especificados no construtor de MyFullEnumerationSimpleSyncProvider:

this.ItemConstraint += new EventHandler<SimpleSyncItemConstraintEventArgs>(OnItemConstraint);
this.ItemConflicting += new EventHandler<SimpleSyncItemConflictingEventArgs>(OnItemConflicting);
AddHandler Me.ItemConstraint, AddressOf HandleItemConstraint

O exemplo de código a seguir mostra os manipuladores de eventos definindo as ações de resolução de conflito como Merge:

void OnItemConstraint(object sender, SimpleSyncItemConstraintEventArgs e)
{
    // Set the resolution action for constraint conflicts.
    // In this sample, the provider checks for duplicates in InsertItem, and this event would
    // fire if a duplicate occurred. 
    e.SetResolutionAction(ConstraintConflictResolutionAction.Merge);
}

void OnItemConflicting(object sender, SimpleSyncItemConflictingEventArgs e)
{
    // Set the resolution action for concurrency conflicts.
    e.SetResolutionAction(ConflictResolutionAction.Merge);
}
Private Sub HandleItemConstraint(ByVal sender As Object, ByVal e As SimpleSyncItemConstraintEventArgs)
    ' Set the resolution action for constraint conflicts. 
    ' In this sample, the provider checks for duplicates in InsertItem, and this event would 
    ' fire if a duplicate occurred. 
    e.SetResolutionAction(ConstraintConflictResolutionAction.Merge)
End Sub

Private Sub HandleItemConflicting(ByVal sender As Object, ByVal e As SimpleSyncItemConflictingEventArgs)
    ' Set the resolution action for concurrency conflicts. 
    e.SetResolutionAction(ConflictResolutionAction.Merge)
End Sub

O exemplo de código a seguir mostra o método MergeConstraintConflict implementado para responder a uma ação de resolução Mesclar para um conflito de restrição:

public void MergeConstraintConflict(object itemData, 
    ConflictVersionInformation conflictVersionInformation, 
    IEnumerable<SyncId> changeUnitsToMerge, 
    ItemFieldDictionary localConflictingItem, 
    ItemFieldDictionary keyAndExpectedVersion, 
    RecoverableErrorReportingContext recoverableErrorReportingContext, 
    out ItemFieldDictionary updatedKeyAndVersion)
{
    ItemTransfer transfer = (ItemTransfer)itemData;
    ItemData dataCopy = new ItemData(transfer.ItemData);

    // Combine the conflicting data.
    ItemData mergedData = (_store.Get(transfer.Id)).Merge((ItemData)dataCopy);

    // We are doing a merge so we must delete the old conflicting item from our store.
    ulong idConflicting = (ulong)localConflictingItem[CUSTOM_FIELD_ID].Value;

    _store.DeleteItem(idConflicting);

    // Now create the new merged data in the store.
    if (_store.Contains(transfer.Id))
    {
        _store.UpdateItem(transfer.Id, dataCopy);
    }
    else
    {
        _store.CreateItem(mergedData, transfer.Id);
    }

    updatedKeyAndVersion = _store.CreateItemFieldDictionary(transfer.Id);
}
Public Sub MergeConstraintConflict(ByVal itemData As Object, ByVal conflictVersionInformation As ConflictVersionInformation, ByVal changeUnitsToMerge As IEnumerable(Of SyncId), ByVal localConflictingItem As ItemFieldDictionary, ByVal keyAndExpectedVersion As ItemFieldDictionary, ByVal recoverableErrorReportingContext As RecoverableErrorReportingContext, _
ByRef updatedKeyAndVersion As ItemFieldDictionary) Implements ISimpleSyncProviderConstraintConflictResolver.MergeConstraintConflict
    Dim transfer As ItemTransfer = DirectCast(itemData, ItemTransfer)
    Dim dataCopy As New ItemData(transfer.ItemData)

    ' Combine the conflicting data. 
    Dim mergedData As ItemData = (_store.[Get](transfer.Id)).Merge(DirectCast(dataCopy, ItemData))

    ' We are doing a merge so we must delete the old conflicting item from our store. 
    Dim idConflicting As ULong = CULng(localConflictingItem(CUSTOM_FIELD_ID).Value)

    _store.DeleteItem(idConflicting)

    ' Now create the new merged data in the store. 
    If _store.Contains(transfer.Id) Then
        _store.UpdateItem(transfer.Id, dataCopy)
    Else
        _store.CreateItem(mergedData, transfer.Id)
    End If

    updatedKeyAndVersion = _store.CreateItemFieldDictionary(transfer.Id)
End Sub

Consulte também

Conceitos

Implementando um provedor personalizado simples
Como criar um provedor simples gerenciado