Condividi tramite


Rilevamento e risoluzione dei conflitti di vincoli

I conflitti di vincoli violano i vincoli imposti su elementi, ad esempio la relazione delle cartelle o il percorso di dati con la stessa denominazione all'interno di un file system. In Sync Framework sono disponibili oggetti di applicazione modifiche che semplificano la risoluzione dei conflitti di vincoli.

I conflitti di vincoli vengono rilevati dal provider di destinazione durante la fase di applicazione modifiche della sincronizzazione. Quando rileva un conflitto di vincoli, il provider di destinazione lo segnala all'oggetto di applicazione modifiche. L'oggetto di applicazione modifiche risolve il conflitto in base ai criteri di risoluzione dei conflitti impostati per la sessione o all'azione di risoluzione dei conflitti impostata dall'applicazione per il conflitto specificato. L'oggetto di applicazione modifiche invia quindi tutte le chiamate necessarie al provider di destinazione in modo che quest'ultimo possa applicare il conflitto risolto alla replica di destinazione.

Quando un provider segnala conflitti di vincoli e utilizza un oggetto di applicazione modifiche, deve fornire anche un log dei conflitti che l'oggetto di applicazione modifiche utilizzerà per elaborare e registrare i conflitti. In Sync Framework è disponibile un'implementazione in memoria di un log dei conflitti per i provider che non ne implementano uno proprio. Per ulteriori informazioni, vedere Registrazione e gestione di conflitti.

Si tenga presente che i conflitti di vincoli non possono essere utilizzati da un provider che utilizza filtri personalizzati o il servizio di applicazione modifiche. In caso contrario, possono verificarsi risultati imprevisti.

Tipi di conflitto di vincoli

Poiché dipendono dall'archivio dati utilizzato dalla replica di destinazione, i conflitti di vincoli possono assumere forme diverse. In Sync Framework i conflitti di vincoli sono suddivisi 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 nella replica di destinazione. Come esempio di conflitto di logica di business, considerare una replica a bassa fedeltà che archivia due unità di modifica: name e country. Considerare inoltre una replica ad alta fedeltà che archivia tre unità di modifica: name, state/province e country. La replica ad alta fedeltà contiene la logica di business che controlla il campo state/province rispetto al campo country e non archivia la modifica che non supera il controllo. La replica a bassa fedeltà viene utilizzata come origine e invia un elemento con country impostato su "USA". Il provider di destinazione tenta di applicare la modifica alla replica ad alta fedeltà, ma nella replica ad alta fedeltà l'elemento contiene "British Columbia" nel campo state/province. Pertanto, la modifica viola la logica di business e causa un conflitto di vincoli.

Il provider di destinazione opera una selezione tra i valori seguenti per specificare la causa di un conflitto di vincoli.

Causa di un conflitto di vincoli Descrizione

Collision (per il codice gestito), CCR_COLLISION (per il codice non gestito)

Questo elemento non può essere salvato perché è in conflitto con un altro elemento presente nell'archivio, ad esempio un elemento avente lo stesso nome di un elemento esistente. Il provider deve specificare l'ID dell'elemento di destinazione come ID dell'elemento in conflitto.

NoParent (per il codice gestito), CCR_NOPARENT (per il codice non gestito)

L'elemento non può essere salvato nell'archivio dati gerarchico perché richiede un elemento padre che non esiste nell'archivio. Facoltativamente, il provider può specificare l'ID dell'elemento padre mancante come ID dell'elemento in conflitto.

Other (per il codice gestito), CCR_OTHER (per il codice non gestito)

L'elemento o l'unità di modifica viola altri vincoli della replica di destinazione. Facoltativamente, il provider può specificare l'ID dell'elemento in conflitto come l'ID elemento in conflitto.

Rilevamento e segnalazione dei conflitti di vincoli

Il rilevamento di un conflitto di vincoli dipende dall'archivio dati utilizzato da una replica. I conflitti di vincoli devono pertanto essere rilevati dal provider di destinazione. Ad esempio, un provider che rappresenta un file system gerarchico deve essere in grado di rilevare vincoli specifici dell'archivio imposti su dati persistenti, ad esempio percorso, denominazione, dimensioni e così via.

I conflitti di vincoli vengono rilevati dal provider di destinazione durante la fase di applicazione modifiche della sincronizzazione.

Codice gestito I conflitti di vincoli vengono in genere rilevati dal provider di destinazione nel relativo metodo SaveItemChange o SaveChangeWithChangeUnits e segnalati tramite la chiamata a RecordConstraintConflictForItem o RecordConstraintConflictForChangeUnit.

Codice non gestito I conflitti di vincoli vengono in genere rilevati dal provider di destinazione nel relativo metodo ISynchronousNotifyingChangeApplierTarget::SaveChange o ISynchronousNotifyingChangeApplierTarget::SaveChangeWithChangeUnits e segnalati tramite la chiamata a ISaveChangeContext2::SetConstraintConflictOnChange o ISaveChangeWithChangeUnitsContext2::SetConstraintConflictOnChangeUnit.

Quando l'oggetto di applicazione modifiche riceve la segnalazione di un conflitto di vincoli, intraprende molteplici azioni:

  • Nel caso di un conflitto di collisione, l'oggetto di applicazione modifiche determina se il conflitto è nuovo, temporaneo o una propagazione della risoluzione tramite unione. Durante l'elaborazione del conflitto, l'oggetto di applicazione modifiche potrebbe archiviare temporaneamente il conflitto nel log dei conflitti chiamando SaveConstraintConflict (per il codice gestito) o ISynchronousNotifyingChangeApplierTarget2::SaveConstraintConflict (per il codice non gestito). L'oggetto di applicazione modifiche rimuove i conflitti temporanei dal log alla fine della sessione di sincronizzazione.

  • Risolve i conflitti di collisione in base ai criteri di risoluzione dei conflitti di collisione impostati per la sessione o in base all'azione di risoluzione dei conflitti determinata dall'applicazione. L'applicazione viene chiamata per determinare l'azione di risoluzione dei conflitti quando i relativi criteri sono impostati su ApplicationDefined (per il codice gestito) o su CCRP_NONE (per il codice non gestito).

  • Risolve i conflitti di vincoli non di tipo collisione in base all'azione di risoluzione dei conflitti determinata dall'applicazione. Non è possibile impostare i criteri di risoluzione dei conflitti per i conflitti di vincoli non di tipo collisione.

Risoluzione dei conflitti di vincoli

L'oggetto di applicazione modifiche assiste il provider di destinazione nella risoluzione dei conflitti di vincoli inviando chiamate all'oggetto di destinazione dell'oggetto di applicazione modifiche specificato dal provider. Quando vengono specificati criteri di risoluzione dei conflitti di collisione, l'oggetto di applicazione modifiche li utilizza per determinare l'azione di risoluzione corretta da intraprendere per risolvere ogni conflitto di collisione che si verifica. Quando viene specificata una risoluzione dei conflitti di collisione personalizzata, l'oggetto di applicazione modifiche notifica il conflitto di collisione all'applicazione di sincronizzazione e quest'ultima specifica l'azione di risoluzione dei conflitti. Non è possibile specificare criteri di risoluzione per i conflitti di vincoli non di tipo collisione, pertanto quando viene segnalato un conflitto di vincoli non di tipo collisione, l'oggetto di applicazione modifiche notifica sempre l'applicazione in modo che possa specificare l'azione di risoluzione dei conflitti. In tutti i casi, l'oggetto di applicazione modifiche chiama il metodo di destinazione appropriato e l'oggetto di destinazione dell'oggetto di applicazione modifiche esegue l'azione, ad esempio il salvataggio della modifica nella replica o la registrazione del conflitto per un'elaborazione successiva.

Definizione dei criteri di risoluzione dei conflitti di collisione

In genere, l'applicazione di sincronizzazione specifica i criteri di risoluzione dei conflitti di collisione prima dell'avvio della sincronizzazione.

Codice gestito L'applicazione specifica i criteri impostando la proprietà CollisionConflictResolutionPolicy del provider di destinazione sul valore desiderato.

Codice non gestito L'applicazione specifica i criteri tramite un meccanismo personalizzato, ad esempio un'interfaccia personalizzata che l'applicazione ottiene chiamando QueryInterface sull'oggetto provider di destinazione.

Il provider di destinazione passa i criteri di risoluzione dei conflitti di collisione al metodo ApplyChanges (per il codice gestito) o ISynchronousNotifyingChangeApplier2::ApplyChanges (per il codice non gestito) dell'oggetto di applicazione modifiche affinché quest'ultimo possa inviare correttamente i metodi all'oggetto di destinazione dell'oggetto di applicazione modifiche. La destinazione dell'oggetto di applicazione modifiche è rappresentata dall'oggetto INotifyingChangeApplierTarget2 (per il codice gestito) o ISynchronousNotifyingChangeApplierTarget2 (per il codice non gestito)

Criteri di risoluzione dei conflitti di collisione per il codice gestito

In Sync Framework vengono definiti i criteri di risoluzione dei conflitti di collisione seguenti per il codice gestito.

Criteri di risoluzione dei conflitti Descrizione

SourceWins

La modifica apportata alla replica di origine prevale sempre. Sync Framework specifica un'azione di risoluzione dei conflitti di SourceWins.

DestinationWins

La modifica apportata nella replica di destinazione prevale sempre. In Sync Framework viene specificata un'azione di risoluzione dei conflitti di DestinationWins.

RenameSource

La modifica inviata dal provider di origine viene rinominata in modo che non sia più in conflitto con l'elemento nella replica di destinazione e la modifica di origine viene applicata alla replica di destinazione. In Sync Framework viene specificata un'azione di risoluzione dei conflitti di RenameSource.

RenameDestination

L'elemento in conflitto nella replica di destinazione viene rinominato in modo che non sia più in conflitto con la modifica inviata dal provider di origine e la modifica di origine viene applicata alla replica di destinazione. In Sync Framework viene specificata un'azione di risoluzione dei conflitti di RenameDestination.

Merge

I dati dell'elemento di origine vengono combinati con l'elemento di destinazione. In Sync Framework viene specificata l'azione di risoluzione dei conflitti di Merge.

ApplicationDefined

L'oggetto di applicazione modifiche notifica all'applicazione di sincronizzazione ogni conflitto di collisione nel momento in cui si verifica tramite l'evento ItemConstraint. L'applicazione esamina gli elementi in conflitto e specifica l'azione di risoluzione dei conflitti chiamando SetResolutionAction.

Criteri di risoluzione dei conflitti di collisione per il codice non gestito

In Sync Framework vengono definiti i criteri di risoluzione dei conflitti di collisione seguenti per il codice non gestito.

Criteri di risoluzione dei conflitti Descrizione

CCRP_SOURCE_PROVIDER_WINS

La modifica apportata nella replica di origine prevale sempre. In Sync Framework viene specificata un'azione di risoluzione dei conflitti di SCRA_ACCEPT_SOURCE_PROVIDER.

CCRP_DESTINATION_PROVIDER_WINS

La modifica apportata nella replica di destinazione prevale sempre. In Sync Framework viene specificata un'azione di risoluzione dei conflitti di SCRA_ACCEPT_DESTINATION_PROVIDER.

CCRP_RENAME_SOURCE

La modifica inviata dal provider di origine viene rinominata in modo che non sia più in conflitto con l'elemento nella replica di destinazione e la modifica di origine viene applicata alla replica di destinazione. In Sync Framework viene specificata un'azione di risoluzione dei conflitti di SCRA_RENAME_SOURCE.

CCRP_RENAME_DESTINATION

L'elemento in conflitto nella replica di destinazione viene rinominato in modo che non sia più in conflitto con la modifica inviata dal provider di origine e la modifica di origine viene applicata alla replica di destinazione. In Sync Framework viene specificata un'azione di risoluzione dei conflitti di SCRA_RENAME_DESTINATION.

CCRP_MERGE

I dati dell'elemento di origine vengono combinati all'elemento di destinazione. In Sync Framework viene specificata un'azione di risoluzione dei conflitti di SCRA_MERGE.

CCRP_NONE

L'oggetto di applicazione modifiche notifica all'applicazione di sincronizzazione ogni conflitto di collisione nel momento in cui si verifica tramite l'evento ISyncConstraintCallback::OnConstraintConflict. L'applicazione esamina gli elementi in conflitto e specifica l'azione di risoluzione dei conflitti chiamando IConstraintConflict::SetConstraintResolveActionForChange o IConstraintConflict::GetConstraintResolveActionForChangeUnit.

Risoluzioni personalizzate dei conflitti

Un'applicazione può specificare un'azione di risoluzione per ogni conflitto di vincoli che si verifica. A tale scopo, deve essere registrata affinché possa ricevere notifica dei conflitti di vincoli. Quando viene segnalato un conflitto di vincoli, Sync Framework notifica l'applicazione, la quale può analizzare il conflitto e impostare l'azione di risoluzione dei conflitti desiderata.

Definizione di risoluzioni personalizzate dei conflitti tramite codice gestito

Per ricevere notifica dei conflitti di collisione, un'applicazione deve eseguire le azioni seguenti prima dell'avvio della sincronizzazione.

  • Registrazione di un gestore dell'evento per l'evento ItemConstraint del provider di destinazione.

  • Impostazione della proprietà CollisionConflictResolutionPolicy del provider di destinazione su ApplicationDefined.

Se queste azioni sono state eseguite, l'oggetto di applicazione modifiche genererà l'evento ItemConstraint una volta per ogni conflitto di vincoli di collisione segnalato durante la sincronizzazione.

Poiché non è possibile specificare criteri di risoluzione per i conflitti di vincoli non di tipo collisione, l'oggetto di applicazione modifiche genererà anche l'evento ItemConstraint una volta per ogni conflitto di vincoli non di tipo collisione segnalato.

Il gestore dell'evento per l'evento ItemConstraint riceve un oggetto ItemConstraintEventArgs contenente metadati e dati dell'elemento per le due modifiche in conflitto. Il gestore dell'evento può esaminare le due modifiche in conflitto, apportare modifiche ai metadati o ai dati dell'elemento e impostare l'azione di risoluzione per il conflitto tramite il metodo SetResolutionAction. L'oggetto di applicazione modifiche elabora quindi il conflitto e invia la chiamata appropriata all'oggetto di destinazione dell'oggetto di applicazione modifiche. Si tenga presente che, quando il conflitto di vincoli non è di tipo collisione, le uniche azioni di risoluzione valide sono SaveConflict e SkipChange.

In Sync Framework è disponibile il set di azioni di risoluzione dei conflitti di vincoli seguente, per il quale l'oggetto di applicazione modifiche gestisce gran parte dell'elaborazione.

Azione di risoluzione dei conflitti Descrizione Valida per tipo di conflitto

SourceWins

La modifica apportata alla replica di origine prevale sempre. L'oggetto di applicazione modifiche passa la modifica al metodo SaveItemChange e specifica un'azione di salvataggio di DeleteConflictingAndSaveSourceItem. La modifica di origine viene applicata alla replica di destinazione e l'elemento di destinazione in conflitto viene eliminato dalla replica di destinazione.

Solo conflitti di collisione.

DestinationWins

La modifica apportata alla replica di destinazione prevale sempre. L'oggetto di applicazione modifiche passa la modifica di origine al metodo SaveItemChange e specifica un'azione di salvataggio di DeleteAndStoreTombstone. Il provider di destinazione crea una rimozione definitiva per la modifica di origine. Quando la destinazione agirà come origine in una sincronizzazione successiva, enumererà una modifica che rappresenta l'eliminazione dell'elemento di origine e lo rimuoverà dalla community di sincronizzazione.

Solo conflitti di collisione.

RenameSource

La modifica inviata dal provider di origine viene rinominata in modo che non sia più in conflitto con l'elemento nella replica di destinazione e la modifica di origine viene applicata alla replica di destinazione. L'oggetto di applicazione modifiche passa la modifica al metodo SaveItemChange e specifica un'azione di salvataggio di RenameSourceAndUpdateVersionAndData.

Solo conflitti di collisione.

RenameDestination

L'elemento in conflitto nella replica di destinazione viene rinominato in modo che non sia più in conflitto con la modifica inviata dal provider di origine e la modifica di origine viene applicata alla replica di destinazione. L'oggetto di applicazione modifiche passa la modifica al metodo SaveItemChange e specifica un'azione di salvataggio di RenameDestinationAndUpdateVersionData.

Solo conflitti di collisione.

Merge

I dati dell'elemento di origine vengono combinati con l'elemento di destinazione. L'oggetto di applicazione modifiche passa i dati di modifica della replica di origine al metodo SaveItemChange e specifica un'azione di salvataggio di ChangeIdUpdateVersionAndMergeData. Per informazioni dettagliate, vedere più avanti Unione di elementi in conflitto.

Solo conflitti di collisione.

SaveConflict

Registrare il conflitto e non applicare la modifica. L'oggetto di applicazione modifiche passa i dati relativi al conflitto al metodo SaveConstraintConflict che salva il conflitto in un log. Per ulteriori informazioni sulla registrazione dei conflitti, vedere Registrazione e gestione di conflitti.

Tutti i conflitti di vincoli.

SkipChange

Ignorare il conflitto e non applicare la modifica. L'oggetto di applicazione modifiche non passa i dati relativi al conflitto al provider di destinazione.

Tutti i conflitti di vincoli.

Definizione di risoluzioni personalizzate dei conflitti tramite codice non gestito

Per ricevere notifica dei conflitti di collisione, un'applicazione deve eseguire le azioni seguenti prima dell'avvio della sincronizzazione.

Se queste azioni sono state eseguite, l'oggetto di applicazione modifiche chiama il metodo OnConstraintConflict una volta per ogni conflitto di vincoli di collisione segnalato durante la sincronizzazione.

Poiché non è possibile specificare criteri di risoluzione per i conflitti di vincoli non di tipo collisione, l'oggetto di applicazione modifiche chiamerà anche il metodo OnConstraintConflict una volta per ogni conflitto di vincoli non di tipo collisione segnalato.

Il metodo OnConstraintConflict riceve un oggetto IConstraintConflict che contiene metadati e dati dell'elemento per le due modifiche in conflitto. Il metodo può esaminare le due modifiche in conflitto, apportare modifiche ai metadati o ai dati dell'elemento e impostare l'azione di risoluzione per il conflitto tramite il metodo IConstraintConflict::SetConstraintResolveActionForChange o IConstraintConflict::GetConstraintResolveActionForChangeUnit. L'oggetto di applicazione modifiche elabora quindi il conflitto e invia la chiamata appropriata all'oggetto di destinazione dell'oggetto di applicazione modifiche. Si tenga presente che, quando il conflitto di vincoli non è di tipo collisione, le uniche azioni di risoluzione valide sono SCRA_TRANSFER_AND_DEFER e SCRA_DEFER.

In Sync Framework è disponibile il set di azioni di risoluzione dei conflitti di vincoli seguente, per il quale l'oggetto di applicazione modifiche gestisce gran parte dell'elaborazione.

Criteri di risoluzione dei conflitti Descrizione Validi per tipo di contenuto

SCRA_ACCEPT_SOURCE_PROVIDER

La modifica apportata alla replica di origine prevale sempre. L'oggetto di applicazione modifiche passa la modifica al metodo ISynchronousNotifyingChangeApplierTarget::SaveChange e specifica un'azione di salvataggio di SSA_DELETE_CONFLICTING_AND_SAVE_SOURCE_ITEM. La modifica di origine viene applicata alla replica di destinazione e l'elemento di destinazione in conflitto viene eliminato dalla replica di destinazione.

Solo conflitti di collisione.

SCRA_ACCEPT_DESTINATION_PROVIDER

La modifica apportata nella replica di destinazione prevale sempre. L'oggetto di applicazione modifiche passa la modifica di origine al metodo SaveChange e specifica un'azione di salvataggio di SSA_DELETE_AND_STORE_TOMBSTONE. Il provider di destinazione crea una rimozione definitiva per la modifica di origine. Quando la destinazione agirà come origine in una sincronizzazione successiva, enumererà una modifica che rappresenta l'eliminazione dell'elemento di origine e lo rimuoverà dalla community di sincronizzazione.

Solo conflitti di collisione.

SCRA_RENAME_SOURCE

La modifica inviata dal provider di origine viene rinominata in modo che non sia più in conflitto con l'elemento nella replica di destinazione e la modifica di origine viene applicata alla replica di destinazione. L'oggetto di applicazione modifiche passa la modifica al metodo SaveChange e specifica un'azione di salvataggio di SSA_RENAME_SOURCE_AND_UPDATE_VERSION_AND_DATA.

Solo conflitti di collisione.

SCRA_RENAME_DESTINATION

L'elemento in conflitto nella replica di destinazione viene rinominato in modo che non sia più in conflitto con la modifica inviata dal provider di origine e la modifica di origine viene applicata alla replica di destinazione. L'oggetto di applicazione modifiche passa la modifica al metodo SaveChange e specifica un'azione di salvataggio di SSA_RENAME_DESTINATION_AND_UPDATE_VERSION_AND_DATA.

Solo conflitti di collisione.

SCRA_MERGE

I dati dell'elemento di origine vengono combinati con l'elemento di destinazione. L'oggetto di applicazione modifiche passa i dati di modifica della replica di origine al metodo SaveChange e specifica un'azione di salvataggio di SSA_CHANGE_ID_UPDATE_VERSION_AND_MERGE_DATA. Per informazioni dettagliate, vedere più avanti Unione di elementi in conflitto.

Solo conflitti di collisione.

SCRA_TRANSFER_AND_DEFER

Registrare il conflitto e non applicare la modifica. L'oggetto di applicazione modifiche passa i dati relativi al conflitto al metodo ISynchronousNotifyingChangeApplierTarget2::SaveConstraintConflict che salva il conflitto in un log. Per ulteriori informazioni sulla registrazione dei conflitti, vedere Registrazione e gestione di conflitti.

Tutti i conflitti di vincoli.

SCRA_DEFER

Ignorare il conflitto e non applicare la modifica. L'oggetto di applicazione modifiche non passa i dati relativi al conflitto al provider di destinazione.

Tutti i conflitti di vincoli.

Unione di elementi in conflitto

L'unione di due elementi in un conflitto di vincoli di collisione è diversa dall'unione di elementi in un conflitto di concorrenza perché i due elementi interessati da un conflitto di collisione presentano ID elemento diversi. Ad esempio, un file denominato "FavoriteBooks.txt" viene creato in una replica con l'ID id1. Un file denominato "FavoriteBooks.txt" viene creato anche in un'altra replica con l'ID id2. Quando le repliche vengono sincronizzate, Sync Framework considera i due elementi diversi perché presentano ID elemento diversi, mentre la replica di destinazione li considera uguali perché presentano lo stesso nome. Il provider di destinazione segnala così un conflitto di collisione e specifica che il contenuto dei due elementi deve essere unito. L'oggetto di applicazione modifiche assegna all'elemento unito l'ID id1 e specifica che la replica di destinazione deve archiviare una rimozione definitiva tramite unione per id2.

Quando un conflitto di collisione viene risolto tramite unione, è necessario selezionare uno degli ID elemento come ID elemento prevalente assegnato all'elemento unito e rilevare correttamente che l'ID elemento non prevalente è stato unito. L'oggetto di applicazione modifiche seleziona l'ID elemento prevalente confrontando i due ID elemento e selezionando l'ID più piccolo come ID prevalente. L'ID elemento prevalente viene utilizzato per identificare l'elemento unito nella replica di destinazione. Nella replica di destinazione viene creata e archiviata una rimozione definitiva tramite unione. La rimozione definitiva tramite unione rileva che l'ID elemento non prevalente identifica lo stesso elemento dell'ID elemento prevalente nella community di sincronizzazione. I metadati di una rimozione definitiva tramite unione sono uguali a quelli utilizzati per la rimozione definitiva di un elemento eliminato, con l'aggiunta dell'ID elemento prevalente.

Codice gestito Se l'azione di risoluzione delle modifiche è Merge, l'oggetto di applicazione modifiche chiama SaveItemChange e specifica un'azione di salvataggio di ChangeIdUpdateVersionAndMergeData. L'oggetto di applicazione modifiche passa la modifica con l'ID elemento non prevalente come parametro change. È possibile ottenere la modifica con l'ID elemento prevalente chiamando il metodo GetWinnerChange dell'oggetto SaveChangeContext passato nel parametro context.

Codice non gestito Se l'azione di risoluzione delle modifiche è SCRA_MERGE, l'oggetto di applicazione modifiche chiama ISynchronousNotifyingChangeApplierTarget::SaveChange e specifica un'azione di salvataggio di SSA_CHANGE_ID_UPDATE_VERSION_AND_MERGE_DATA. L'oggetto di applicazione modifiche passa la modifica con l'ID elemento non prevalente come parametro pChange. È possibile ottenere la modifica con l'ID elemento prevalente chiamando il metodo ISaveChangeContext2::GetWinnerChange dell'oggetto ISaveChangeContext2 passato nel parametro pSaveContext.

Il provider di destinazione deve eseguire molteplici passaggi per elaborare correttamente l'unione. Si consideri un'azione di unione che specifica id1 come ID elemento non prevalente e id2 come ID elemento prevalente. Il provider di destinazione deve eseguire i passaggi seguenti in una transazione.

  1. Archiviare una rimozione definitiva tramite unione nei metadati di destinazione. La rimozione definitiva tramite unione contiene id1 come ID elemento non prevalente e id2 come ID elemento prevalente. Se esiste già una rimozione definitiva tramite unione nella replica di destinazione che contiene id1 come ID elemento non prevalente e un altro ID elemento, id3, come ID elemento prevalente, il provider esegue i passaggi seguenti.

    1. Se id2 è maggiore di id3, il provider crea e archivia due rimozioni definitive tramite unione. Una di esse contiene id1 come ID elemento non prevalente e id2 come ID elemento prevalente. L'altra contiene id2 come ID elemento non prevalente e id3 come ID elemento prevalente. È possibile che questa seconda rimozione definitiva tramite unione esista già, nel qual caso viene semplicemente ignorata. In questo modo viene creata una catena di rimozioni definitive tramite unione, in ordine decrescente per ID elemento.

    2. Se id3 è maggiore di id2, il provider restituisce un errore.

  2. Esegue l'unione dei dati per l'elemento nella replica di destinazione con i dati per l'elemento dal provider di origine. L'elemento di destinazione può essere identificato da id1 o id2.

  3. Applica i metadati per la modifica nei metadati di destinazione e i dati uniti per la modifica nell'archivio di elementi di destinazione, utilizzando l'ID elemento prevalente, id2, come ID elemento per la modifica unita. È possibile ottenere i metadati per la modifica chiamando il metodo GetWinnerChange di context (per il codice gestito) o il metodo GetWinnerChange di pContext (per il codice non gestito).

Propagazione di un elemento unito

La propagazione di elementi uniti da un conflitto di vincoli di collisione è diversa dalla propagazione di elementi uniti da un conflitto di concorrenza perché possono verificarsi conflitti con l'ID elemento prevalente, l'ID elemento non prevalente o entrambi. Ad esempio, la replica X contiene un elemento con ID id1 unito dagli elementi con ID id1 e id2. La replica Y contiene un elemento con ID id2 e ha apportato modifiche locali all'elemento. Quando l'elemento unito identificato da id1 viene inviato dalla replica X alla replica Y, si crea un conflitto perché id1 fa ora riferimento allo stesso elemento di id2.

L'oggetto di applicazione modifiche assiste il provider di destinazione nell'applicazione di una modifica di un elemento unito rilevando i conflitti di concorrenza che si verificano sia con l'ID elemento prevalente sia con l'ID elemento non prevalente e determinando l'azione corretta che il provider di destinazione deve eseguire per applicare la modifica di un elemento unito alla replica di destinazione. Se il provider di destinazione rileva un conflitto di vincoli quando applica una modifica di un elemento unito, deve segnalare il conflitto di vincoli come qualsiasi altro.

L'oggetto di applicazione modifiche rileva inoltre quando la replica di origine e la replica di destinazione non concordano sull'identità di un elemento. Ad esempio, la replica X risolve un conflitto di collisione tra elementi con ID id1 e id2 eseguendo l'unione degli elementi e assegnando id1 all'elemento unito. La replica Y risolve un conflitto di collisione tra elementi con ID id1 e id2 rinominando l'elemento identificato da id1 e mantenendo entrambi gli elementi. La replica X invia l'elemento unito identificato da id1 e una rimozione definitiva tramite unione che indica che id2 è stato unito in id1. Il conflitto su id1 viene rilevato e risolto come un conflitto di concorrenza. Il conflitto su id2 viene rilevato e segnalato all'applicazione di sincronizzazione come un conflitto di identità specificando la causa del conflitto di Identity (per il codice gestito) o CCR_IDENTITY (per il codice non gestito). L'applicazione determina se risolvere il conflitto mantenendo la modifica di origine o la modifica di destinazione.

Si tenga presente che, quando il provider di origine utilizza il filtro delle unità di modifica e il provider di destinazione non è filtrato, può verificarsi un conflitto di identità anche quando l'elemento identificato dalla rimozione definitiva tramite unione deve essere rimosso dalla replica di destinazione. Questa situazione si verifica a causa del modo in cui la conoscenza filtrata viene gestita dall'oggetto di applicazione modifiche. Per garantire una sincronizzazione corretta e la propagazione della rimozione definitiva tramite unione, il provider di destinazione deve conservare la rimozione definitiva tramite unione e rimuovere l'elemento in conflitto dalla replica di destinazione.

Quando il provider di origine invia una modifica di un elemento unito, l'oggetto di applicazione modifiche determina l'azione corretta che il provider di destinazione deve eseguire per applicare la modifica alla replica di destinazione. Nella tabella seguente sono elencate le azioni di salvataggio che l'oggetto di applicazione modifiche può specificare e le azioni che il provider deve eseguire per applicare la modifica.

Azione di salvataggio Azioni del provider

ChangeIdUpdateVersionAndSaveData (per il codice gestito), SSA_CHANGE_ID_UPDATE_VERSION_AND_SAVE_DATA (per il codice non gestito)

Archiviare una rimozione definitiva tramite unione per l'ID elemento non prevalente, eseguendo gli stessi passaggi indicati più indietro in Unione di elementi in conflitto. Applicare la modifica dell'elemento prevalente.

ChangeIdUpdateVersionOnly (per il codice gestito), SSA_CHANGE_ID_UPDATE_VERSION_ONLY (per il codice non gestito)

Archiviare una rimozione definitiva tramite unione per l'ID elemento non prevalente, eseguendo gli stessi passaggi indicati più indietro in Unione di elementi in conflitto. Applicare solo i metadati per la modifica dell'elemento prevalente.

ChangeIdUpdateVersionAndDeleteAndStoreTombstone (per il codice gestito), SSA_CHANGE_ID_UPDATE_VERSION_AND_DELETE_AND_STORE_TOMBSTONE (per il codice non gestito)

Archiviare una rimozione definitiva tramite unione per l'ID elemento non prevalente, eseguendo gli stessi passaggi indicati più indietro in Unione di elementi in conflitto. Eliminare l'elemento identificato dall'ID elemento prevalente e archiviare una rimozione definitiva per tale elemento.

StoreMergeTombstone (per il codice gestito), SSA_STORE_MERGE_TOMBSTONE (per il codice non gestito)

Archiviare una rimozione definitiva tramite unione per l'ID elemento non prevalente, eseguendo gli stessi passaggi indicati più indietro in Unione di elementi in conflitto.

Nota

Tutti i passaggi di un'azione di salvataggio devono essere applicati come un'azione atomica.

Vedere anche

Riferimento

Interfaccia ISaveChangeContext2
Interfaccia ISaveChangeWithChangeUnitsContext2
Interfaccia ISynchronousNotifyingChangeApplier2
Interfaccia ISynchronousNotifyingChangeApplierTarget2
SaveChangeContext
SaveChangeWithChangeUnitsContext
NotifyingChangeApplier
INotifyingChangeApplierTarget2

Concetti

Gestione dei conflitti
Rilevamento e risoluzione dei conflitti di concorrenza