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:
Aktivieren der Momentaufnahmenisolation für die Datenbank
Festlegen der zu synchronisierenden Tabellen
Erstellen von Nachverfolgungstabellen, um tabellenbasierte Metadaten zu speichern, und von Indizes für die entsprechenden Tabellen
Erstellen von Triggern für die einzelnen Basistabellen, um die Nachverfolgungstabellen aufzufüllen und zu aktualisieren
(Optional) Bearbeiten von in der Datenbank vorhandenen Daten
Erstellen einer Nachverfolgungstabelle, um bereichsbasierte Metadaten zu speichern, und eines Index für diese Tabelle
Definieren der zu synchronisierenden Bereiche, um festzulegen, welche Tabellen als Einheit synchronisiert werden sollen
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“.
Die Zeile „Q“ wird von Client A aktualisiert und anschließend mit der Datenbank synchronisiert.
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.
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:
Node1 und Node2 synchronisieren alle Änderungen.
Node1 synchronisiert mit Node3.
Ein Benutzer führt bei Node2 eine Aktualisierung durch.
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:
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'')
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 Filterstate=WA
undorder_details
mit dem Filterstate=WA
.Bereich 2 ist
sales-OR
. Dieser Bereich beinhaltet:products
;orders
mit dem Filterstate=OR
undorder_details
mit dem Filterstate=OR
.
In diesem Szenario wird die gesamte Tabelle
products
von beiden Bereichen gemeinsam verwendet. Die Tabellenorders
undorder_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 Filterstate=WA
undorder_details
mit dem Filterstate=WA
.Bereich 2 ist
sales-Northwest
. Dieser Bereich beinhaltet:products
;orders
mit dem Filterstate=WA OR state=ID
undshippers
.
Auch in diesem Szenario wird die gesamte Tabelle
products
von beiden Bereichen gemeinsam verwendet. Die Tabelleorders
ist in beiden Bereichen vorhanden, und die Filter überlappen sich. Beide Bereiche verwenden die Zeilen gemeinsam, die für den Filterstate=WA
gelten. Die Tabellenshippers
undorder_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.
SelectIncrementalChangesCommand
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)