Condividi tramite


Gestione dei conflitti per i provider semplici

Se possibile, progettare applicazioni per evitare conflitti. Il rilevamento e la risoluzione dei conflitti comportano un aumento del traffico di rete e un'intensificazione dell'elaborazione e della complessità. In alcune applicazioni i conflitti non possono essere evitati. In un'applicazione di gestione della forza vendita, ad esempio, due venditori potrebbero condividere un'area geografica. Entrambi i venditori potrebbero aggiornare i dati per lo stesso cliente e per gli stessi ordini. Per assicurarsi che le modifiche apportate agli elementi nella community di sincronizzazione vengano propagate correttamente, il provider di destinazione deve rilevare e gestire i conflitti che si verificano tra gli elementi inviati dal provider di origine e gli elementi nella replica di destinazione. Sync Framework fornisce gli oggetti che eseguono la maggior parte delle operazioni necessarie per rilevare e gestire i conflitti.

Sync Framework rileva i conflitti a livello dell'elemento o dell'unità di modifica. Sync Framework riconosce due categorie di conflitti che possono verificarsi durante la sincronizzazione: conflitti di concorrenza e conflitti di vincoli. I conflitti di concorrenza si verificano quando lo stesso elemento o unità di modifica viene modificata in due repliche diverse, sincronizzate in un secondo momento. I conflitti di vincoli violano i vincoli imposti su elementi o unità di modifica, ad esempio la relazione delle cartelle o il percorso di dati con la stessa denominazione all'interno di un file system. Sync Framework suddivide i conflitti di vincoli nei tre tipi seguenti.

  • Si verifica un conflitto di collisione quando l'elemento non può essere salvato perché è in conflitto con un altro elemento nell'archivio di destinazione, ad esempio quando il provider di origine invia un file avente lo stesso nome e percorso di un file già esistente sulla replica di destinazione.

  • Si verifica un conflitto di elemento padre mancante quando un elemento non può essere salvato in un archivio dati gerarchico perché manca un elemento padre, ad esempio quando il provider di origine invia un file da salvare in una directory che non esiste nella replica di destinazione.

  • Si verificano altri conflitti di vincoli quando l'elemento da salvare viola un vincolo della replica di destinazione, ad esempio quando il provider di origine invia un file di dimensioni troppo elevate per poter essere salvato nella replica di destinazione o quando la modifica viola in qualche modo la logica di business sulla replica di destinazione.

I vincoli sono correlati alle funzionalità specifiche di un archivio di elementi, ad esempio i vincoli di chiave esterna che sono comuni nei database. I provider semplici supportano solo i conflitti di vincoli di collisione. Per ulteriori informazioni sulla gestione dei conflitti per provider personalizzati standard, vedere Rilevamento e risoluzione dei conflitti di vincoli.

Informazioni sulla gestione dei conflitti

Per decidere come gestire i conflitti di concorrenza e di vincoli, è necessario rispondere a due domande importanti:

  • I conflitti devono essere risolti automaticamente durante la sincronizzazione o è necessario che l'applicazione riceva una notifica al rilevamento di un conflitto in modo che possa guidare la risoluzione?

  • Tutti i conflitti devono essere risolti specificando la prevalenza della destinazione o dell'origine oppure è necessaria una gestione dei conflitti più sofisticata? Ad esempio, in un conflitto di concorrenza, è possibile eseguire l'unione dei dati di origine e di destinazione in un solo elemento applicato a entrambe le repliche.

Dopo avere risposto a queste domande, è possibile specificare il comportamento di Sync Framework in caso di rilevamento di un conflitto:

  1. Specificare i criteri di risoluzione per i conflitti di concorrenza e per i conflitti di vincoli di collisione. I criteri determinano se Sync Framework risolve automaticamente il conflitto o se l'applicazione risponde per impostazione predefinita a un evento per la gestione del conflitto.

    Se si specificano criteri diversi da quelli predefiniti, Sync Framework imposta l'azione appropriata per la risoluzione dei conflitti quando si verifica un conflitto. Ad esempio, se si specificano i criteri "prevale l'origine" per i conflitti di concorrenza, l'azione "prevale l'origine" viene impostata se viene rilevato un conflitto di quel tipo durante una sessione di sincronizzazione. Se si accetta l'impostazione predefinita per uno o per entrambi i criteri di risoluzione, il provider o l'applicazione deve rispondere agli eventi che vengono generati quando viene rilevato un conflitto. Il provider può rispondere implementando i metodi seguenti:

    Se il provider non implementa questi metodi, i callback dell'applicazione seguenti vengono utilizzati in modo che l'applicazione possa impostare l'azione di risoluzione. Se l'applicazione non risponde a questi eventi, la risoluzione del conflitto viene posticipata fino alla sessione di sincronizzazione successiva. In questo caso, il conflitto non verrà mai risolto, a meno che non cambino i dati in conflitto o l'applicazione.

    In risposta al conflitto, il provider o l'applicazione deve impostare un'azione di risoluzione.

    Oltre all'impostazione dell'azione di risoluzione, è possibile includere codice personalizzato nel gestore dell'evento. Ad esempio, è possibile visualizzare elementi in conflitto in un'interfaccia utente man mano che vengono elaborati.

  2. Per alcune delle azioni di risoluzione impostate da Sync Framework o dall'applicazione, è necessario implementare una o entrambe le interfacce seguenti:

    Per i conflitti di concorrenza, i metodi di risoluzione implementati per queste interfacce si differenziano dal tipo di conflitti a cui rispondono, ad esempio un conflitto aggiornamento-aggiornamento. Per i conflitti di vincoli, i metodi di risoluzione implementati si differenziano dal risultato della risoluzione, ad esempio la ridenominazione dell'elemento di origine.

    Per i conflitti di concorrenza, se l'azione viene impostata su Merge (per il codice gestito) o su SRA_MERGE (per il codice non gestito), è necessario implementare i metodi seguenti che gestiscono i tre tipi di conflitti di concorrenza:

    L'implementazione deve eseguire l'unione degli elementi in conflitto in un modo appropriato per la replica e l'applicazione, finché è presente un elemento finale che rappresenta i due elementi in conflitto.

    Per i conflitti di vincoli di collisione, implementare i metodi in base alle azioni che è possibile impostare:

Esempio di codice gestito

In questo esempio i criteri di gestione dei conflitti per i conflitti di concorrenza e di vincoli corrispondono all'impostazione predefinita di ApplicationDefined. Ciò significa che l'applicazione verrà registrata per gli eventi ItemConflicting e ItemConstraint e specificherà un'azione per risolvere i conflitti che si dovessero eventualmente verificare durante l'elaborazione della sincronizzazione. Nell'esempio di codice seguente vengono illustrati i gestori eventi specificati nel costruttore di MyFullEnumerationSimpleSyncProvider:

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

Nell'esempio di codice seguente vengono illustrati i gestori eventi che impostano le azioni di risoluzione dei conflitti su 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

Nell'esempio di codice seguente viene illustrato il metodo MergeConstraintConflict implementato per rispondere a un'azione di risoluzione di tipo unione per un conflitto di vincoli:

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

Vedere anche

Concetti

Implementazione di un provider personalizzato semplice
Procedura: creare un provider semplice gestito