Freigeben über


Konfliktbehandlung für einfache Anbieter

Entwerfen Sie Anwendungen so, dass Konflikte vermieden werden, soweit dies möglich ist. Konflikterkennung und -auflösung führen zu zusätzlicher Komplexität, Verarbeitung und mehr Netzwerkverkehr. In einigen Anwendungen können Konflikte nicht vermieden werden. Beispielsweise könnten zwei Vertriebsmitarbeiter in einer Außendienstanwendung für dieselbe Region zuständig sein. Beide Vertriebsmitarbeiter könnten die Daten für den gleichen Kunden und die gleichen Bestellungen aktualisieren. Um sicherzustellen, dass an Elementen in der Synchronisierungscommunity vorgenommene Änderungen ordnungsgemäß weitergegeben werden, muss der Zielanbieter Konflikte zwischen den vom Quellenanbieter gesendeten Elementen und den Elementen im Zielreplikat erkennen und lösen. Sync Framework stellt Objekte bereit, die bei der Erkennung und Behandlung von Konflikten die Hauptarbeit übernehmen.

Sync Framework erkennt Konflikte auf der Ebene des Elements oder der Änderungseinheit. Sync Framework erkennt zwei Kategorien von Konflikten, die während der Synchronisierung auftreten können: Parallelitätskonflikte und Einschränkungskonflikte. Parallelitätskonflikte treten auf, wenn dasselbe Element oder dieselbe Änderungseinheit auf zwei verschiedenen Replikaten geändert werden, die später synchronisiert werden. Einschränkungskonflikte sind Konflikte, bei denen für Elemente oder Änderungseinheiten geltende Einschränkungen (z. B. die Beziehung zwischen Ordnern oder der Speicherort identisch benannter Daten innerhalb eines Dateisystems) verletzt werden. Sync Framework unterscheidet, wie im Folgenden dargestellt, drei Arten von Einschränkungskonflikten.

  • Ein Kollisionskonflikt tritt auf, wenn das Element nicht gespeichert werden kann, da es mit einem anderen Element im Zielspeicher in Konflikt steht, wenn beispielsweise der Quellenanbieter eine Datei sendet, die den gleichen Namen und Speicherort wie eine Datei aufweist, die bereits im Zielreplikat vorhanden ist.

  • Ein Konflikt aufgrund eines fehlenden übergeordneten Elements tritt auf, wenn ein Element nicht in einem hierarchischen Datenspeicher gespeichert werden kann, da es ein nicht vorhandenes übergeordnetes Element erfordert, wenn beispielsweise der Quellenanbieter eine Datei sendet, die in einem Verzeichnis gespeichert werden soll, das auf dem Zielreplikat nicht vorhanden ist.

  • Andere Einschränkungskonflikte treten auf, wenn das zu speichernde Element gegen eine Einschränkung des Zielreplikats verstößt, wenn beispielsweise der Quellenanbieter eine Datei sendet, die zu groß ist, um auf dem Zielreplikat gespeichert zu werden, oder wenn die Änderung gegen eine bestimmte Geschäftslogik des Zielreplikats verstößt.

Einschränkungen beziehen sich auf bestimmte Funktionen eines Elementspeichers, z. B. Fremdschlüsseleinschränkungen, die häufig in Datenbanken auftreten. Einfache Anbieter unterstützen nur Kollisionseinschränkungskonflikte. Weitere Informationen zur Konfliktbehandlung für benutzerdefinierte Standardanbieter finden Sie unter Erkennen und Auflösen von Einschränkungskonflikten.

Grundlegendes zur Konfliktbehandlung

Um zu entscheiden, wie Parallelitätskonflikte und Einschränkungskonflikte behandelt werden, müssen zwei wichtige Fragen beantwortet werden:

  • Sollen Konflikte während der Synchronisierung automatisch aufgelöst werden, oder soll die Anwendung bei Erkennung eines Konflikts benachrichtigt werden, damit sie die Konfliktauflösung steuern kann?

  • Sollen alle Konflikte durch die Angabe des Vorrangs von Quelle oder Ziel aufgelöst werden, oder ist eine ausgereiftere Konfliktbehandlung erforderlich? Beispielsweise sollten Sie bei einem Parallelitätskonflikt möglicherweise die Quell- und Zieldaten zu einem einzelnen Element zusammenführen, das auf beide Replikate angewendet wird.

Nachdem Sie diese Fragen beantwortet haben, können Sie angeben, wie sich Sync Framework bei Auftreten eines Konflikts verhalten soll:

  1. Geben Sie eine Auflösungsrichtlinie für Parallelitäts- und Kollisionseinschränkungskonflikte an. Die Richtlinie bestimmt, ob Sync Framework den Konflikt automatisch auflöst oder ob die Anwendung standardmäßig auf ein Ereignis reagiert, um den Konflikt zu behandeln.

    Wenn Sie eine andere Richtlinie als den Standard angeben, legt Sync Framework bei Auftreten eines Konflikts die entsprechende Konfliktauflösungsaktion fest. Wenn Sie z. B. die Richtlinie "Die Quelle hat Vorrang" für Parallelitätskonflikte angeben, wird die Aktion "Die Quelle hat Vorrang" festgelegt, wenn ein Konflikt dieses Typs während einer Synchronisierungssitzung erkannt wird. Wenn Sie den Standard für eine oder beide Auflösungsrichtlinien übernehmen, muss der Anbieter oder die Anwendung auf Ereignisse reagieren, die durch die Erkennung eines Konflikts ausgelöst werden. Der Anbieter kann durch Implementierung der folgenden Methoden reagieren:

    Wenn der Anbieter diese Methoden nicht implementiert, werden die folgenden Anwendungsrückrufe verwendet, damit die Anwendung die Auflösungsaktion festlegen kann. Wenn die Anwendung nicht auf diese Ereignisse reagiert, wird die Lösung des Konflikts bis zu einer nachfolgenden Synchronisierungssitzung verzögert. In dieser Situation wird der Konflikt gar nicht aufgelöst, bis die Konflikt verursachenden Daten oder die Anwendung geändert werden.

    Als Antwort auf den Konflikt muss der Anbieter oder die Anwendung eine Auflösungsaktion festlegen.

    Zusätzlich zum Festlegen der Auflösungsaktion können Sie auch benutzerdefinierten Code in den Ereignishandler einschließen. Sie können z. B. Konflikt verursachende Elemente während ihrer Verarbeitung auf einer Benutzeroberfläche anzeigen.

  2. Für einige der Auflösungsaktionen, die von Sync Framework oder von der Anwendung festlegt werden, müssen Sie eine oder beide der folgenden Schnittstellen implementieren:

    Bei Parallelitätskonflikten unterscheiden sich die Auflösungsmethoden, die Sie für diese Schnittstellen implementieren, durch den Typ der Konflikte, auf die sie reagieren, wie z. B. ein UPDATE-UPDATE-Konflikt. Bei Einschränkungskonflikten unterscheiden sich die Auflösungsmethoden, die Sie implementieren, durch das Ergebnis der Auflösung, wie z. B. das Umbenennen des Quellelements.

    Wenn bei Parallelitätskonflikten die Aktion auf Merge (für verwalteten Code) oder SRA_MERGE (für nicht verwalteten Code) festgelegt wird, müssen die folgenden Methoden zur Behandlung der drei Typen von Parallelitätskonflikten implementiert werden:

    Die Implementierung sollte die Konflikt verursachenden Elemente auf eine für das Replikat und die Anwendung geeignete Weise zusammenführen, sofern es ein abschließendes Element gibt, das die zwei Konflikt verursachenden Elemente darstellt.

    Implementieren Sie Methoden für Kollisionseinschränkungskonflikte auf Grundlage der Aktionen, die festgelegt werden können:

Beispiel für verwalteten Code

In diesem Beispiel werden die Konfliktbehandlungsrichtlinien für Parallelitätskonflikte und Einschränkungskonflikte wie bei der Standardeinstellung von ApplicationDefined beibehalten. Dies bedeutet, dass die Anwendung für das ItemConflicting-Ereignis und ItemConstraint-Ereignis registriert wird und eine Aktion zur Auflösung von Konflikten festgelegt wird, die bei der Synchronisierungsverarbeitung auftreten. Im folgenden Codebeispiel werden die Ereignishandler veranschaulicht, die im Konstruktor von MyFullEnumerationSimpleSyncProvider angegeben werden:

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

Im folgenden Codebeispiel werden die Ereignishandler veranschaulicht, die die Konfliktauflösungsaktionen auf Merge festlegen:

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

Im folgenden Codebeispiel wird die MergeConstraintConflict-Methode veranschaulicht, die als Antwort auf eine Auflösungsaktion von "Merge" für einen Einschränkungskonflikt implementiert wird:

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

Siehe auch

Konzepte

Implementieren eines benutzerdefinierten einfachen Anbieters
Vorgehensweise: Erstellen eines verwalteten einfachen Anbieters