Freigeben über


Vorgehensweise: Bereitstellen einer Serverdatenbank für die Synchronisierung für die Zusammenarbeit (Nicht-SQL Server)

Hinweis

In den Themen in diesem Abschnitt der Dokumentation, Synchronisieren von anderen ADO.NET-kompatiblen Datenbanken, wird veranschaulicht, wie andere Datenbanken als SQL Server mithilfe von Sync Framework synchronisiert werden können. In dieser Version wird in Codebeispielen SQL Server verwendet. Der Code kann jedoch für andere ADO.NET-kompatible Datenbanken verwendet werden, wenn einige Änderungen an den SQL Server-spezifischen Objekten (z. B. SqlConnection) und den angezeigten SQL-Abfragen vorgenommen werden. Informationen über die Synchronisierung von SQL Server finden Sie unter Vorgehensweise: Konfigurieren und Ausführen der Synchronisierung für die Zusammenarbeit (SQL Server).

In diesem Thema wird beschrieben, wie eine von DbSyncProvider synchronisierte Datenbank bereitgestellt wird, um inkrementelle Datenänderungen in dieser Datenbank nachverfolgen zu können. Die Änderungen werden nachverfolgt, damit diese bei einer Synchronisierungssitzung auf andere Knoten angewendet werden können. Um eine Datenbank für Sync Framework bereitzustellen, führen Sie folgende Schritte aus:

  1. Aktivieren der Momentaufnahmenisolation für die Datenbank

  2. Festlegen der zu synchronisierenden Tabellen

  3. Erstellen von Nachverfolgungstabellen, um tabellenbasierte Metadaten zu speichern, und von Indizes für die entsprechenden Tabellen

  4. Erstellen von Triggern für die einzelnen Basistabellen, um die Nachverfolgungstabellen aufzufüllen und zu aktualisieren

  5. (Optional) Bearbeiten von in der Datenbank vorhandenen Daten

  6. Erstellen einer Nachverfolgungstabelle, um bereichsbasierte Metadaten zu speichern, und eines Index für diese Tabelle

  7. Definieren der zu synchronisierenden Bereiche, um festzulegen, welche Tabellen als Einheit synchronisiert werden sollen

  8. Erstellen gespeicherter Prozeduren, um Daten und Metadaten auszuwählen und zu aktualisieren

Diese Schritte sind für Datenbanken nicht erforderlich, die mit SqlCeSyncProvider synchronisiert werden. Die Bereitstellung wird bei der Initialisierung der Datenbank von Sync Framework durchgeführt.

Nachdem eine Datenbank bereitgestellt wurde, kann sie mit anderen Knoten synchronisiert werden. Weitere Informationen zur Konfiguration und Ausführung einer Synchronisierung finden Sie unter Vorgehensweise: Konfigurieren und Ausführen der Synchronisierung für die Zusammenarbeit (Nicht-SQL Server).

Aktivieren der Momentaufnahmenisolation für die Datenbank

In der Änderungsenumerationsphase einer Synchronisierungssitzung werden die Transaktionen von Sync Framework unter Momentaufnahmenisolation gestartet. Um Transaktionen unter Momentaufnahmenisolation zu starten, müssen Sie die Datenbankoption ALLOW_SNAPSHOT_ISOLATION auf ON festlegen (siehe folgendes Codebeispiel):

ALTER DATABASE [database name] SET ALLOW_SNAPSHOT_ISOLATION ON

Weitere Informationen finden Sie in der SQL Server-Onlinedokumentation.

Festlegen der zu synchronisierenden Tabellen

Der erste Schritt beim Bereitstellen der Datenbank ist das Identifizieren der zu synchronisierenden Tabellen. Jede Tabelle muss über einen Primärschlüssel verfügen. Betrachten Sie folgendes Codebeispiel. Es zeigt das Sales.Customer-Tabellenschema in der Datenbank SyncSamplesDb_Peer1 an.

CREATE TABLE Sales.Customer(
    CustomerId uniqueidentifier NOT NULL PRIMARY KEY DEFAULT NEWID(), 
    CustomerName nvarchar(100) NOT NULL,
    SalesPerson nvarchar(100) NOT NULL,
    CustomerType nvarchar(100) NOT NULL)

Die einzelnen zu synchronisierenden Tabellen verfügen über ein zugeordnetes DbSyncAdapter-Objekt. Sie geben den Primärschlüssel in der Auflistung RowIdColumns des Objekts an. Weitere Informationen finden Sie unter Vorgehensweise: Konfigurieren und Ausführen der Synchronisierung für die Zusammenarbeit (Nicht-SQL Server).

Tabellen können leer sein oder vorhandene Daten enthalten. Wenn die Tabelle vorhandene Zeilen von Daten enthält, die synchronisiert werden sollen, müssen Sie sicherstellen, dass jede Zeile einen Metadateneintrag in der entsprechenden Tabelle für die Änderungsnachverfolgung aufweist. Weitere Informationen finden Sie unter Behandeln von vorhandenen Daten in der Datenbank.

Erstellen von Nachverfolgungstabellen für tabellenbasierte Metadaten

In Sync Framework ist eine Methode erforderlich, mit der überprüft wird, welche Zeilen seit der letzten Synchronisierungssitzung zwischen zwei Knoten geändert wurden. Änderungen werden mithilfe zweier verschiedener Metadatentypen dargestellt:

  • Tabellenbasierte Metadaten, mit denen Einfügungen, Aktualisierungen und Löschvorgänge für alle zu synchronisierenden Tabellen nachverfolgt werden.

  • Bereichsbasierte Metadaten, mit denen Änderungen nachverfolgt werden, die die einzelnen Knoten von anderen Knoten erhalten haben.

Tabellenbasierte Metadaten werden mit je einer Nachverfolgungstabelle für jede Basistabelle nachverfolgt. Die Basis- und Nachverfolgungstabellen müssen in allen Datenbanken vorhanden sein, die mit DbSyncProvider synchronisiert werden. Der Primärschlüssel der Nachverfolgungstabelle ist der gleiche wie der in der Basistabelle. Außerdem sind zusätzliche Spalten erforderlich. Diese Spalten werden in der folgenden Tabelle beschrieben. Die Namen der zusätzlichen Spalten müssen nicht mit den aufgelisteten identisch sein. Sie müssen jedoch hinsichtlich der Reihenfolge und des Typs den Abfragen oder Prozeduren entsprechen, die auf die Nachverfolgungstabellen zugreifen. Einige dieser Prozeduren sind in Erstellen gespeicherter Prozeduren, um Daten und Metadaten auszuwählen und zu aktualisieren enthalten.

Spalte Beschreibung Aktualisiert wenn...…

<Primärschlüssel der Basistabelle> – Umfasst eine Spalte für jede Primärschlüsselspalte.

Primärschlüsselspalten der Basistabelle.

Der Basistabelle wird eine Zeile hinzugefügt. Die Einfügung kann vom lokalen oder vom Remoteknoten stammen.

update_scope_local_id

Die ID des Bereichs, der die letzte Aktualisierung oder Löschung ausgeführt hat. Für Aktualisierungen oder Löschvorgänge, die vom lokalen Knoten stammen, ist diese Spalte NULL.

Verweist auf die Spalte „scope_local_id“ der Bereichsinformationstabelle. Weitere Informationen finden Sie unter „Erstellen von Nachverfolgungstabellen für bereichsbasierte Metadaten“.

Aktualisierungen oder Löschvorgänge von einem Remoteknoten werden auf die Basistabelle angewendet.

scope_update_peer_key

Die Identität des Knotens, der die letzte Aktualisierung oder Löschung ausgeführt hat.

Aktualisierungen oder Löschvorgänge von einem Remoteknoten werden auf die Basistabelle angewendet.

scope_update_peer_timestamp

Der Timestampwert der Remotedatenbank für den Zeitpunkt, zu dem die Zeile ursprünglich aktualisiert oder gelöscht wurde.

Aktualisierungen oder Löschvorgänge von einem Remoteknoten werden auf die Basistabelle angewendet.

local_update_peer_key

Die Identität des lokalen Knotens. Diese Spalte enthält für die einzelnen Zeilen den Wert „0“. Dies gilt nicht, wenn die lokale Datenbank aus einer Sicherung wiederhergestellt wurde. 1

Eine Aktualisierung oder Löschung eines lokalen Vorgangs oder von einem Remoteknoten wird auf die Basistabelle angewendet.

local_update_peer_timestamp

Der Timestampwert der lokalen Datenbank für den Zeitpunkt, zu dem die Zeile aktualisiert oder in der lokalen Datenbank gelöscht wurde. 1

Eine Aktualisierung oder Löschung eines lokalen Vorgangs oder von einem Remoteknoten wird auf die Basistabelle angewendet.

create_scope_local_id

Die Identität des Bereichs, der die Einfügung durchgeführt hat. Für Aktualisierungen oder Löschvorgänge, die vom lokalen Knoten stammen, ist diese Spalte NULL.

Verweist auf die Spalte „scope_local_id“ der Bereichsinformationstabelle. Weitere Informationen finden Sie in „Erstellen von Nachverfolgungstabellen für bereichsbasierte Metadaten“ unter Vorgehensweise: Bereitstellen einer Serverdatenbank für die Synchronisierung für die Zusammenarbeit (Nicht-SQL Server).

Eine Einfügung von einem Remoteknoten wird auf die Basistabelle angewendet.

scope_create_peer_key

Die Identität des Knotens, der die Einfügung durchgeführt hat.

Eine Einfügung von einem Remoteknoten wird auf die Basistabelle angewendet.

scope_create_peer_timestamp

Der Timestampwert der Remotedatenbank für den Zeitpunkt, zu dem die Zeile ursprünglich eingefügt wurde.

Eine Einfügung von einem Remoteknoten wird auf die Basistabelle angewendet.

local_create_peer_key

Die Identität des lokalen Knotens. Diese Spalte enthält für die einzelnen Zeilen den Wert „0“. Dies gilt nicht, wenn die lokale Datenbank aus einer Sicherung wiederhergestellt wurde. 1

Eine Einfügung von einem lokalen Vorgang oder einem Remoteknoten wird auf die Basistabelle angewendet.

local_create_peer_timestamp

Der Timestampwert der lokalen Datenbank für den Zeitpunkt, zu dem die Zeile in die lokale Datenbank eingefügt wurde. 1

Eine Einfügung von einem lokalen Vorgang oder einem Remoteknoten wird auf die Basistabelle angewendet.

sync_row_is_tombstone

Der Wert 1 gibt an, dass ein Metadateneintrag für eine Löschung in der Basistabelle besteht.

Eine Zeile wird aus der Basistabelle gelöscht. Der Löschvorgang kann vom lokalen oder vom Remoteknoten stammen.

last_change_datetime

Das Datum und die Uhrzeit, zu dem die Metadatenzeile zuletzt aktualisiert wurde.

Eine Zeile dieser Nachverfolgungstabelle wird eingefügt oder aktualisiert.

restore_timestamp

Speichert den Wert von „local_update_peer_timestamp“ für den Zeitpunkt einer Datenbankwiederherstellung. Der Wert wird anschließend als lokaler Wert für den Aktualisierungszeitstempel verwendet.

In der Regel ist dieser Wert auf NULL gesetzt, er kann jedoch vom Wiederherstellungsprozess festgelegt werden. Er wird bei jeder Aktualisierung einer Zeile auf NULL festgelegt.

<Filterspalten> – Fügen Sie für jede Nicht-Primärschlüsselspalte eine Spalte hinzu, die in der WHERE-Filterklausel für alle Bereiche verwendet wird.

Nur erforderlich, wenn eine Tabelle für mindestens einen Bereich gefiltert wird. Speichert den Wert der gefilterten Spalten für Einfügungen, Aktualisierungen und Löschvorgänge.

Eine Zeile wird eingefügt, aktualisiert oder aus der Basistabelle gelöscht. Der Löschvorgang kann vom lokalen oder vom Remoteknoten stammen.

1 Wird von Sync Framework verwendet, wenn überlappende Bereiche synchronisiert werden. Im folgenden Beispiel finden Sie Aktualisierungen für eine Datenbank, bei denen Bereich X mit Client A und Bereich Y mit Client B synchronisiert wird. Beide Bereiche enthalten die Zeile „Q“.

  1. Die Zeile „Q“ wird von Client A aktualisiert und anschließend mit der Datenbank synchronisiert.

  2. Client B synchronisiert mit der Datenbank und erhält die Aktualisierung von Zeile „Q“.

    Client B beachtet Bereich X nicht. Daher muss die Änderung von Client A so dargestellt werden, als stamme sie von der Datenbank. Dies wird bei der Synchronisierung mit Client B oder anderen Clients, die den in „update_scope_local_id“ gespeicherten Bereich für Zeile „Q“ nicht synchronisieren, mithilfe der Werte von „local_update_peer_key“ und „local_update_peer_timestamp“ erreicht.

  3. Die Zeile „Q“ wird in der Datenbank aktualisiert und anschließend von Client A aktualisiert.

    Client A beachtet Bereich X. Daher werden die Werte von „scope_update_peer_key“ und „scope_update_peer_timestamp“ beim Synchronisieren mit Client A oder einem beliebigen anderen Client verwendet, der Bereich X synchronisiert.

Es wird empfohlen, ein separates Datenbankschema für die Nachverfolgungstabelle und alle anderen Objekte zu erstellen, die sich auf Synchronisierungsmetadaten beziehen. Dadurch können die Metadaten von den Daten der Basistabellen isoliert werden. Erstellen Sie im Sinne einer optimalen Leistung für die einzelnen Nachverfolgungstabellen Indizes:

  • Wenn Daten nicht gefiltert werden: Verwenden Sie den gleichen Primärschlüssel wie für die Basistabelle, und erstellen Sie einen nicht gruppierten Index (local_update_peer_timestamp)

  • Wenn Daten gefiltert werden: Verwenden Sie den gleichen Primärschlüssel wie für die Basistabelle, und erstellen Sie einen nicht gruppierten Index für (local_update_peer_timestamp, <Filterspalten>, <Primärschlüsselspalten>)

In den folgenden Codebeispielen wird eine Tabelle im Sync-Schema erstellt, das Änderungen für die Tabelle Sales.Customer nachverfolgt. Zudem wird der Tabelle ein Index hinzugefügt.

CREATE TABLE Sync.Customer_Tracking(
    
    CustomerId uniqueidentifier NOT NULL PRIMARY KEY,          
    
    update_scope_local_id int NULL, 
    scope_update_peer_key int,
    scope_update_peer_timestamp bigint,
    local_update_peer_key int,
    local_update_peer_timestamp timestamp,

    create_scope_local_id int NULL,
    scope_create_peer_key int,
    scope_create_peer_timestamp bigint,
    local_create_peer_key int,
    local_create_peer_timestamp bigint,

    sync_row_is_tombstone int, 
    restore_timestamp bigint, 
    last_change_datetime datetime default NULL)

CREATE NONCLUSTERED INDEX NonClustered_Customer_Tracking
ON Sync.Customer_Tracking ([local_update_peer_timestamp])

Erstellen von Triggern, um Nachverfolgungstabellen aufzufüllen und zu aktualisieren

Im Anschluss an das Erstellen der Nachverfolgungstabellen fügen Sie allen Basistabellen die Trigger INSERT, UPDATE und DELETE hinzu. Wenn eine Zeile einer Basistabelle von einem Benutzer oder von Sync Framework eingefügt, aktualisiert oder gelöscht wird, wird ein Trigger ausgelöst, und die Metadaten für diese Zeile werden eingefügt oder in der Tabelle für die Änderungsnachverfolgung aktualisiert. Wenn die Änderung an der Basistabelle auf Sync Framework angewendet wurde (da diese von einem anderen Knoten stammte), wird die Tabelle für die Änderungsnachverfolgung in Sync Framework aktualisiert, um den Ursprung der Änderung darzustellen.

Im folgenden Beispiel wird ein Trigger erstellt, der die Metadaten der Änderungsnachverfolgung in der Sales.Customer_Tracking-Tabelle aktualisiert, wenn eine Aktualisierung an der Sales.Customer-Tabelle durchgeführt wird. Beispiele für Trigger für Einfüge- und Löschvorgänge finden Sie unter Setupskripts für Datenbankanbieter - Themen zur Vorgehensweise.

CREATE TRIGGER Customer_UpdateTrigger ON Sales.Customer FOR UPDATE
AS    
    UPDATE t    
    SET 
        update_scope_local_id = NULL, local_update_peer_key = 0, 
        restore_timestamp = NULL, last_change_datetime = GetDate() 
    FROM Sync.Customer_Tracking t JOIN inserted i ON t.[CustomerId] = i.[CustomerId]        

Behandeln von vorhandenen Daten in der Datenbank

Die Änderungsnachverfolgungs-Metadaten für die einzelnen Tabellen werden mithilfe von Triggern in der Basistabelle eingefügt und aktualisiert. Daher enthalten Änderungsnachverfolgungs-Tabellen keine Informationen zu Zeilen, die vor dem Hinzufügen der Trigger in eine Basistabelle eingefügt wurden. Um vorhandene Daten in der Datenbank zu behandeln, sollten für die vorhandenen Daten Metadaten eingefügt werden. Anschließend werden bei der ersten Synchronisierungssitzung alle Zeilen als neue Einfügungen an die Zieldatenbank gesendet. Im folgenden Codebeispiel wird der Befehl dargestellt, der für die einzelnen Basistabellen ausgeführt werden muss, nachdem der Basistabelle Trigger hinzugefügt wurden:

INSERT INTO [tracking table] ([pk columns], create_scope_local_id, local_create_peer_key, local_create_peer_timestamp, update_scope_local_id, local_update_peer_key, restore_timestamp, sync_row_is_tombstone)
SELECT [pk columns], NULL, 0, @@DBTS+1, NULL, 0, NULL, 0 from [base table] baseT left outer join [tracking table] trackingT
On baseT.[pk columns]=trackingT.[pk columns]
where tracking.[pk columns] is null

Erstellen von Nachverfolgungstabellen für bereichsbasierte Metadaten

Bereichsbasierte Metadaten werden in den einzelnen Datenbanken in der Regel mithilfe zweier Tabellen nachverfolgt:

  • In der Bereichsinformationstabelle wird für die einzelnen Bereiche das Synchronisierungswissen in einem Binärformat gespeichert. Bei einem Bereich handelt es sich um eine logische Gruppierung von Tabellen, mit der definiert wird, welche Daten als Einheit synchronisiert werden sollen.

  • Mit der Bereichszuordnungstabelle wird ermittelt, welche Tabellen einer Datenbank zu einem bestimmten Bereich gehören. Eine Tabelle kann mehreren Bereichen angehören. Die Zuordnungstabelle muss für jedes Paar von <Bereich/Tabelle> einen Eintrag enthalten.

In Sync Framework wird Wissen verwendet, um festzulegen, welche Änderungen bei der Synchronisierung an die einzelnen Datenbanken gesendet werden. Anwendungen müssen nicht direkt auf das Wissen zugreifen. Im Folgenden finden Sie eine bidirektionale Synchronisierungstopologie mit drei Knoten:

  1. Node1 und Node2 synchronisieren alle Änderungen.

  2. Node1 synchronisiert mit Node3.

  3. Ein Benutzer führt bei Node2 eine Aktualisierung durch.

  4. Node3 synchronisiert mit Node2.

Wenn Node3 mit Node2 synchronisiert, verfügt Node3 bereits über die meisten der Änderungen von Node2, da Node3 zuvor mit Node1 synchronisiert wurde. Dank des Wissens wird dies in Sync Framework erkannt, sodass nur die bei Node2 aufgetretene Aktualisierung synchronisiert wird. Weitere Informationen über Wissen finden Sie unter Synchronisierungswissen.

Die Spalten der Bereichsinformationstabelle werden in der folgenden Tabelle beschrieben.

Spalte Beschreibung Aktualisiert wenn...…

scope_id

Ein Bezeichner für den Bereich, in der Regel eine GUID.

Wird nie aktualisiert

scope_local_id

Ein ganzzahliger Bezeichner für den Bereich. Hierbei sollte es sich um eine IDENTITY-Spalte handeln.

Wird nie aktualisiert

scope_name

Der Name des Bereichs.

Wird nie aktualisiert

scope_sync_knowledge

Eine binäre Darstellung des Synchronisierungswissens für die einzelnen Bereiche.

Alle Änderungen wurden für eine Synchronisierungssitzung auf ein Ziel angewendet.

scope_tombstone_cleanup_knowledge

Eine binäre Darstellung des vergessenen Wissens der einzelnen Bereiche. Das vergessene Wissen wird für Metadaten verwendet, die bereinigt wurden.

Alle Änderungen wurden für eine Synchronisierungssitzung auf ein Ziel angewendet.

scope_timestamp

Der Timestampwert für den Zeitpunkt, zu dem die Metadatenzeile zuletzt aktualisiert wurde.

Eine Zeile in dieser Nachverfolgungstabelle wird aktualisiert.

scope_cleanup_timestamp

Der Timestampwert für den Zeitpunkt, zu dem die letzte Tombstonebereinigung für diesen Bereich ausgeführt wurde.

Die Tombstones werden für einen anderen Bereich bereinigt, der überlappende Tabellen aufweist.

Im folgenden Codebeispiel wird eine Bereichsinformationstabelle erstellt.

CREATE TABLE Sync.ScopeInfo(       
    scope_local_id int IDENTITY(1,1),
    scope_id uniqueidentifier default NEWID(),
    scope_name nvarchar(100) NOT NULL PRIMARY KEY,
    scope_sync_knowledge varbinary(max) NULL,
    scope_tombstone_cleanup_knowledge varbinary(max) NULL,
    scope_timestamp timestamp,
    scope_cleanup_timestamp bigint)

Die Bereichsinformationstabelle wird fast immer abgefragt, um beruhend auf dem Bereichsnamen Informationen zu einem bestimmten Bereich abzurufen. Daher wird der Primärschlüssel anhand der Spalte scope_name definiert.

Die Spalten der Bereichszuordnungstabelle werden in der folgenden Tabelle beschrieben.

Spalte Beschreibung Aktualisiert wenn...…

table_name

Der Name der Tabelle.

Wird nie aktualisiert

scope_name

Der Name des Bereichs.

Wird nie aktualisiert

In den folgenden Codebeispielen werden eine Bereichszuordnungstabelle und ein Index für diese Tabelle erstellt.

CREATE TABLE Sync.ScopeTableMap(       
    scope_name nvarchar(100) ,
    table_name nvarchar(100)     
    )

CREATE UNIQUE CLUSTERED INDEX Clustered_ScopeTableMap ON Sync.ScopeTableMap(scope_name, table_name)

Definieren von zu synchronisierenden Bereichen

Im Anschluss an das Erstellen der Bereichstabellen muss mindestens ein zu synchronisierender Bereich festgelegt werden. So können Sie beispielsweise den Bereich Sales definieren und die Tabellen Customer, CustomerContact, OrderHeader und OrderDetail in diesen Bereich einschließen. Bei der Synchronisierung des Bereichs Sales werden die an den vier Tabellen vorgenommenen Änderungen zwischen den beiden Knoten ausgetauscht. Das Definieren eines Bereichs erfolgt in zwei Schritten:

  1. Fügen Sie der Bereichsinformationstabelle und der Bereichszuordnungstabelle Einträge hinzu (siehe folgendes Codebeispiel).

    INSERT INTO Sync.ScopeInfo(scope_name) VALUES (''Sales'')
    INSERT INTO Sync.ScopeTableMap(scope_name, table_name) VALUES (''Sales'', ''Sales.Customer'')
    INSERT INTO Sync.ScopeTableMap(scope_name, table_name) VALUES (''Sales'', ''Sales.CustomerContact'')
    
  2. Geben Sie den Bereichsnamen für die ScopeName-Eigenschaft des DbSyncProvider-Objekts an, und fügen Sie allen Tabellen, die Sie in den Bereich einschließen möchten, ein DbSyncAdapter-Objekt hinzu. Weitere Informationen finden Sie unter „Anwendungscode für ScopeName und Verbindung“ unter Vorgehensweise: Konfigurieren und Ausführen der Synchronisierung für die Zusammenarbeit (Nicht-SQL Server).

Wichtig

Nachdem ein Bereich zum ersten Mal synchronisiert wurde, sollte der Bereich nicht geändert werden. Das Ändern von Tabellen im Bereich oder das Filtern von Klauseln für diese Tabellen kann dazu führen, dass die Daten nicht übereinstimmen.

Gefilterte und überlappende Bereiche

Ein Bereich wird gefiltert, wenn nur eine Teilmenge der Zeilen der Basistabelle im Bereich enthalten ist. So können Sie z. B. den gefilterten Bereich sales-WA definieren, der nur die Umsatzdaten für den Staat Washington enthält. Um die Daten zu filtern, muss die festgelegte Abfrage oder Prozedur für die SelectIncrementalChangesCommand-Eigenschaft des DbSyncAdapter-Objekts eine WHERE-Klausel umfassen, mit der die entsprechenden Daten ausgewählt werden. Die Abfrage oder Prozedur sollte Änderungen anhand der Filterspalten in der Nachverfolgungstabelle auswählen, nicht anhand der Filterspalten in der Basistabelle.

Die folgenden Filterungsarten werden nicht unterstützt:

  • Spaltenfilterung: Alle Spalten müssen in den Abfragen oder Prozeduren enthalten sein, mit denen Änderungen ausgewählt und angewendet werden.

  • Aktualisierungen von Spalten, die für die Filterung verwendet werden: Wenn ein Benutzer einen Wert in einer Spalte aktualisiert, die für Filterung verwendet wird, wird eine Zeile von einem Bereich in einen anderen verschoben. Die Zeile wird an den neuen Bereich gesendet, zu dem die Zeile nun gehört. Sie wird jedoch nicht aus dem alten Bereich gelöscht.

Zwei Bereiche überlappen, wenn sie gemeinsame allgemeine Daten aufweisen. So kann beispielsweise die Tabelle products in den Bereich sales ebenso wie in den Bereich inventory eingeschlossen werden. Bereiche können sowohl überlappend als auch gefiltert sein. Mithilfe der folgenden Szenarien werden Methoden veranschaulicht, in denen eine Filterung und eine Überlappung auftreten können:

  • Szenario 1:

    • Bereich 1 ist sales-WA. Dieser Bereich beinhaltet: products; orders mit dem Filter state=WA und order_details mit dem Filter state=WA.

    • Bereich 2 ist sales-OR. Dieser Bereich beinhaltet: products; orders mit dem Filter state=OR und order_details mit dem Filter state=OR.

    In diesem Szenario wird die gesamte Tabelle products von beiden Bereichen gemeinsam verwendet. Die Tabellen orders und order_details sind in beiden Bereichen vorhanden, die Filter überlappen jedoch nicht. Daher werden in den Bereichen keine Zeilen aus diesen Tabellen gemeinsam verwendet.

  • Szenario 2:

    • Bereich 1 ist sales-WA. Dieser Bereich beinhaltet: products; orders mit dem Filter state=WA und order_details mit dem Filter state=WA.

    • Bereich 2 ist sales-Northwest. Dieser Bereich beinhaltet: products; orders mit dem Filter state=WA OR state=ID und shippers.

    Auch in diesem Szenario wird die gesamte Tabelle products von beiden Bereichen gemeinsam verwendet. Die Tabelle orders ist in beiden Bereichen vorhanden, und die Filter überlappen sich. Beide Bereiche verwenden die Zeilen gemeinsam, die für den Filter state=WA gelten. Die Tabellen shippers und order_details werden nicht von beiden Bereichen verwendet.

Es gibt verschiedene Methoden für die Definition von Bereichen. Dabei gilt jedoch stets folgendes Prinzip: Alle Daten, die zwischen zwei Datenbanken in der Synchronisierungstopologie synchronisiert werden, dürfen nur einem Bereich angehören. So können z. B. im oben angeführten Szenario 2 die Datenbanken A und B Bereich 1 und die Datenbanken A und C Bereich 2 synchronisieren. Die Datenbanken A und B können den Bereich 2 nicht synchronisieren, da die Zeilen products und orders beiden Bereichen angehören.

Erstellen gespeicherter Prozeduren, um Daten und Metadaten auszuwählen und zu aktualisieren

Nachdem Sie Metadatentabellen erstellt haben, können Sie SQL-Abfragen oder gespeicherte Prozeduren (empfohlen) erstellen, um Änderungen an den Basis- und Metadatentabellen auszuwählen und anzuwenden. Aus Leistungs- und Sicherheitsgründen werden gespeicherte Prozeduren empfohlen. Diese Abfragen oder Prozeduren werden für die folgenden DbSyncAdapter-Befehle festgelegt. Diese Befehle werden in „Synchronisierungsadapter“ unter Vorgehensweise: Konfigurieren und Ausführen der Synchronisierung für die Zusammenarbeit (Nicht-SQL Server) beschrieben.

In den folgenden Codebeispielen wird ein Satz gespeicherter Prozeduren erstellt, mit denen Änderungen an Daten und Metadaten in der Sales.Customer-Tabelle bearbeitet werden. Der Kürze halber sind die Prozeduren zum Auswählen der Daten und zur Durchführung von Aktualisierungen enthalten, jene für Einfügungen und Löschvorgänge jedoch nicht. Beispiele für Prozeduren zum Einfügen und Löschen finden Sie unter Setupskripts für Datenbankanbieter - Themen zur Vorgehensweise. Eine Vorlage, mit der diese gespeicherten Prozeduren einfacher erstellt werden können, finden Sie unter Vorlage zur Serverbereitstellung.

Im vollständigen Codebeispiel am Ende dieses Themas stammen viele der an diese Prozeduren übergebenen Werte aus Sitzungsvariablen. Bei diesen handelt es sich um integrierte Variablen, mit denen Sync Framework während einer Synchronisierungssitzung Werte an Befehle übergeben kann. Weitere Informationen über Sitzungsvariablen finden Sie unter Vorgehensweise: Verwenden von Sitzungsvariablen für die Synchronisierung für die Zusammenarbeit.

Prozedur für 'SelectIncrementalChangesCommand'

create procedure Sync.sp_Customer_SelectChanges (
    @sync_min_timestamp bigint,
    @sync_metadata_only int,
    @sync_scope_local_id int,
    @sync_initialize int
)
as

--if @sync_initialize = 0
--begin
    -- Perform additional logic if required.
--end
    
begin
    select  t.CustomerId, 
            c.CustomerName,
            c.SalesPerson,
            c.CustomerType, 
            t.sync_row_is_tombstone,
            t.local_update_peer_timestamp as sync_row_timestamp, 
            case when (t.update_scope_local_id is null or t.update_scope_local_id <> @sync_scope_local_id) 
                 then case when (t.restore_timestamp is null) then t.local_update_peer_timestamp else t.restore_timestamp end else t.scope_update_peer_timestamp end as sync_update_peer_timestamp,
            case when (t.update_scope_local_id is null or t.update_scope_local_id <> @sync_scope_local_id) 
                 then t.local_update_peer_key else t.scope_update_peer_key end as sync_update_peer_key,
            case when (t.create_scope_local_id is null or t.create_scope_local_id <> @sync_scope_local_id) 
                 then t.local_create_peer_timestamp else t.scope_create_peer_timestamp end as sync_create_peer_timestamp,
            case when (t.create_scope_local_id is null or t.create_scope_local_id <> @sync_scope_local_id) 
                 then t.local_create_peer_key else t.scope_create_peer_key end as sync_create_peer_key
    from Sales.Customer c right join Sync.Customer_Tracking t on c.CustomerId = t.CustomerId
    where t.local_update_peer_timestamp > @sync_min_timestamp
end

Prozedur für 'UpdateCommand'

CREATE PROCEDURE Sync.sp_Customer_ApplyUpdate (                                    
        @CustomerId uniqueidentifier,
        @CustomerName nvarchar(100),
        @SalesPerson nvarchar(100),
        @CustomerType nvarchar(100),
        @sync_min_timestamp bigint ,                                
        @sync_row_count int OUT,
        @sync_force_write int)        
AS      
    UPDATE c
    SET c.CustomerName = @CustomerName, c.SalesPerson = @SalesPerson, c.CustomerType = @CustomerType      
    FROM Sales.Customer c JOIN Sync.Customer_Tracking t ON c.CustomerId = t.CustomerId
    WHERE ((t.local_update_peer_timestamp <= @sync_min_timestamp) OR @sync_force_write = 1)
        AND t.CustomerId = @CustomerId  
    SET @sync_row_count = @@rowcount

Prozedur für 'UpdateMetadataCommand'

create procedure Sync.sp_Customer_UpdateMetadata (
        @CustomerId uniqueidentifier,
        @sync_scope_local_id int,
        @sync_row_is_tombstone int,
        @sync_create_peer_key int,
        @sync_create_peer_timestamp bigint,                 
        @sync_update_peer_key int,
        @sync_update_peer_timestamp timestamp,                      
        @sync_row_timestamp timestamp,
        @sync_check_concurrency int,        
        @sync_row_count int out)        
as  
    declare @was_tombstone int
    select @was_tombstone = sync_row_is_tombstone from Sync.Customer_Tracking 
    where CustomerId = @CustomerId
    
    if (@was_tombstone is not null and @was_tombstone=1 and @sync_row_is_tombstone=0)
        -- tombstone is getting resurrected, update creation version as well
        update Sync.Customer_Tracking set
            [update_scope_local_id] = @sync_scope_local_id, 
            [scope_update_peer_key] = @sync_update_peer_key,
            [scope_update_peer_timestamp] = @sync_update_peer_timestamp,
            [local_update_peer_key] = 0,
            [restore_timestamp] = NULL,
            [create_scope_local_id] = @sync_scope_local_id, 
            [scope_create_peer_key] = @sync_create_peer_key, 
            [scope_create_peer_timestamp] =  @sync_create_peer_timestamp, 
            [sync_row_is_tombstone] = @sync_row_is_tombstone                        
        where CustomerId = @CustomerId          
        and (@sync_check_concurrency = 0 or local_update_peer_timestamp = @sync_row_timestamp)
    else    
        update Sync.Customer_Tracking set
            [update_scope_local_id] = @sync_scope_local_id, 
            [scope_update_peer_key] = @sync_update_peer_key,
            [scope_update_peer_timestamp] = @sync_update_peer_timestamp,
            [local_update_peer_key] = 0,
            [restore_timestamp] = NULL,
            [sync_row_is_tombstone] = @sync_row_is_tombstone                        
        where CustomerId = @CustomerId          
        and (@sync_check_concurrency = 0 or local_update_peer_timestamp = @sync_row_timestamp)
    set @sync_row_count = @@rowcount

Prozedur für 'SelectRowCommand'

create procedure Sync.sp_Customer_SelectRow
        @CustomerId uniqueidentifier,
        @sync_scope_local_id int
as
    select  t.CustomerId, 
            c.CustomerName,
            c.SalesPerson,
            c.CustomerType, 
            t.sync_row_is_tombstone,
            t.local_update_peer_timestamp as sync_row_timestamp, 
            case when (t.update_scope_local_id is null or t.update_scope_local_id <> @sync_scope_local_id) 
                 then case when (t.restore_timestamp is null) then t.local_update_peer_timestamp else t.restore_timestamp end else t.scope_update_peer_timestamp end as sync_update_peer_timestamp,
            case when (t.update_scope_local_id is null or t.update_scope_local_id <> @sync_scope_local_id) 
                 then t.local_update_peer_key else t.scope_update_peer_key end as sync_update_peer_key,
            case when (t.create_scope_local_id is null or t.create_scope_local_id <> @sync_scope_local_id) 
                 then t.local_create_peer_timestamp else t.scope_create_peer_timestamp end as sync_create_peer_timestamp,
            case when (t.create_scope_local_id is null or t.create_scope_local_id <> @sync_scope_local_id) 
                 then t.local_create_peer_key else t.scope_create_peer_key end as sync_create_peer_key
    from Sales.Customer c right join Sync.Customer_Tracking t on c.CustomerId = t.CustomerId    
    where c.CustomerId = @CustomerId 

Prozedur für 'SelectMetadataForCleanupCommand'

CREATE PROCEDURE Sync.sp_Customer_SelectMetadata     
    @metadata_aging_in_days int,
    @sync_scope_local_id int
AS
    IF @metadata_aging_in_days = -1
        BEGIN
            SELECT  CustomerId,
                    local_update_peer_timestamp as sync_row_timestamp,  
                    case when (update_scope_local_id is null or update_scope_local_id <> @sync_scope_local_id) 
                        then case when (restore_timestamp is null) then local_update_peer_timestamp else restore_timestamp end else scope_update_peer_timestamp end as sync_update_peer_timestamp,
                    case when (update_scope_local_id is null or update_scope_local_id <> @sync_scope_local_id) 
                        then local_update_peer_key else scope_update_peer_key end as sync_update_peer_key,
                    case when (create_scope_local_id is null or create_scope_local_id <> @sync_scope_local_id) 
                        then local_create_peer_timestamp else scope_create_peer_timestamp end as sync_create_peer_timestamp,
                    case when (create_scope_local_id is null or create_scope_local_id <> @sync_scope_local_id) 
                        then local_create_peer_key else scope_create_peer_key end as sync_create_peer_key
            FROM Sync.Customer_Tracking
            WHERE sync_row_is_tombstone = 1
        END
    
    ELSE
        BEGIN
            SELECT  CustomerId,
                    local_update_peer_timestamp as sync_row_timestamp,  
                    case when (update_scope_local_id is null or update_scope_local_id <> @sync_scope_local_id) 
                        then case when (restore_timestamp is null) then local_update_peer_timestamp else restore_timestamp end else scope_update_peer_timestamp end as sync_update_peer_timestamp,
                    case when (update_scope_local_id is null or update_scope_local_id <> @sync_scope_local_id) 
                        then local_update_peer_key else scope_update_peer_key end as sync_update_peer_key,
                    case when (create_scope_local_id is null or create_scope_local_id <> @sync_scope_local_id) 
                        then local_create_peer_timestamp else scope_create_peer_timestamp end as sync_create_peer_timestamp,
                    case when (create_scope_local_id is null or create_scope_local_id <> @sync_scope_local_id) 
                        then local_create_peer_key else scope_create_peer_key end as sync_create_peer_key
            FROM Sync.Customer_Tracking
            WHERE sync_row_is_tombstone = 1 AND
            DATEDIFF(day, last_change_datetime, GETDATE()) > @metadata_aging_in_days
        END

Zusammenfassung

Anhand dieses Themas haben Sie erfahren, wie Sie eine Datenbank für die Änderungsnachverfolgung bereitstellen können. Nachdem eine Datenbank bereitgestellt wurde, kann sie mit anderen Knoten synchronisiert werden. Weitere Informationen zur Konfiguration und Ausführung einer Synchronisierung finden Sie in den folgenden Themen: Vorgehensweise: Konfigurieren und Ausführen der Synchronisierung für die Zusammenarbeit (Nicht-SQL Server).

Siehe auch

Konzepte

Synchronisieren von anderen ADO.NET-kompatiblen Datenbanken
Vorgehensweise: Konfigurieren und Ausführen der Synchronisierung für die Zusammenarbeit (Nicht-SQL Server)