Freigeben über


Vorgehensweise: Konfigurieren und Ausführen der Synchronisierung für die Zusammenarbeit (SQL Server)

In diesem Thema werden die wichtigsten Bestandteile einer Anwendung beschrieben, die Sync Framework zur Synchronisierung von SQL Server- und SQL Server Compact-Datenbanken verwendet. Der Code dieser Anwendung ist auf die folgenden Sync Framework-Klassen ausgerichtet:

Weitere Informationen dazu, wie Sie Beispielcode ausführen können, finden Sie unter „Beispielanwendungen in den Themen zur Vorgehensweise“ in Synchronisieren von SQL Server und SQL Server Compact.

Wie in Architektur und Klassen der Synchronisierung für die Zusammenarbeit beschrieben, kann die Synchronisierung zwischen zwei Instanzen von SqlSyncProvider, zwei Instanzen von SqlCeSyncProvider oder jeweils einer Instanz auftreten. Der Beispielcode in diesem Thema stammt aus einer 2-Ebenen-Anwendung; daher veranschaulicht er nicht das Synchronisieren zweier Instanzen von SqlCeSyncProvider, die eine n-Ebenen-Konfiguration erfordern. Ein Beispiel für eine n-Ebenen-Konfiguration finden Sie im Sync Framework-SDK im Beispiel „WebSharingAppDemo-CEProviderEndToEnd“.

Vergleichen von Anbietertypen

In diesem Thema wird beschrieben, wie SQL Server- und SQL Server Compact-Datenbanken mit den zwei Synchronisierungsanbietern synchronisiert werden, die in Sync Framework 2.0 eingeführt wurden: SqlSyncProvider und SqlCeSyncProvider. Sync Framework enthält weitere Anbieter, mit denen diese Datenbanken synchronisiert werden können. Die neuen Anbieter sind jedoch im Allgemeinen besser für diese Aufgabe geeignet. Dies hat folgende Gründe:

  • SqlSyncProvider weist den gleichen Funktionsumfang wie DbSyncProvider auf, erfordert jedoch wesentlich weniger Code und weniger Kenntnisse zu den Abfragen, die Sync Framework zum Synchronisieren von Daten verwendet. DbSyncProvider ist weiterhin geeignet für Nicht-SQL Server-Datenbanken.

  • SqlSyncProvider und SqlCeSyncProvider können für Client/Server-, Peer-to-Peer- und gemischte Topologien verwendet werden, wohingegen DbServerSyncProvider und SqlCeClientSyncProvider nur für Client/Server-Topologien geeignet sind. SqlSyncProvider und SqlCeSyncProvider unterstützen außerdem erweiterte Funktionen, wie z. B. Batchverarbeitung von Änderungen basierend auf der Größe der Daten anstatt der Anzahl der Zeilen.

  • SqlSyncProvider und SqlCeSyncProvider sind flexibel und leicht einzurichten. Mit ihnen können alle Editionen von SQL Server synchronisiert werden, einschließlich SQL Server Express und SQL Server Compact.

Einrichten von Knoten und Ausführen der Synchronisierung

Das Synchronisieren von Knoten in einer Topologie kann in zwei Phasen unterteilt werden: die Einrichtung der zu synchronisierenden Knoten sowie die eigentliche Ausführung der Synchronisierung zwischen einem Knotenpaar. Für SqlSyncProvider und SqlCeSyncProvider besteht das Einrichten von Knoten aus zwei Aufgaben:

  1. Definieren, was synchronisiert werden soll

    Sie definieren, was synchronisiert werden soll, indem Sie einen oder mehrere Bereiche beschreiben. Ein Bereich ist ein Satz von Tabellen, von denen einige oder alle gefiltert werden können. Tabellen können bereits in der Datenbank vorhanden sein, oder sie können mit Sync Framework-Objekten beschrieben und dann hat zur Laufzeit generiert werden, wenn der zugrunde liegende Speicher synchronisiert wird. Weitere Informationen dazu finden Sie im Abschnitt „Grundlegendes zu Bereichen“ weiter unten.

    Wichtig

    Nachdem ein Bereich zum ersten Mal synchronisiert wurde, sollten Metadaten, die vorhandenen Bereichen zugeordnet sind, verworfen und neu erstellt werden, wenn ein Bereich geändert werden muss.

  2. Bereitstellen von Datenbanken für die Sync Framework-Änderungsnachverfolgung

    Nachdem die Tabellen und Bereiche beschrieben wurden, verwenden Sie Sync Framework-Objekte, um Bereitstellungsskripts auf jeden Knoten anzuwenden. Die Skripts erstellen eine Infrastruktur zur Änderungsnachverfolgung und Änderungsanwendung, die aus Metadatentabellen, Triggern und gespeicherten Prozeduren besteht.

Nachdem Knoten bereitgestellt wurden, können sie synchronisiert werden. Für den Entwickler ist das Festlegen von Synchronisierungsoptionen und das Aufrufen von Synchronize() unkompliziert. Im Hintergrund verwendet Sync Framework die von Ihnen angegebenen Informationen der Bereichs- und Tabellenbeschreibung, um ein Konfigurationsobjekt für jeden Bereich und jeden Synchronisierungsadapter (einer pro Tabelle) zu erstellen. Dadurch kann Sync Framework die Informationen abrufen, die in jeder Datenbank enthalten sind, und die Informationen zusammenstellen, die für die einzelnen Synchronisierungssitzungen zwischen einem Knotenpaar erforderlich sind. Sowohl SqlSyncProvider als auch SqlCeSyncProvider erkennen die Änderungsnachverfolgungstabellen und andere Objekte, die bei der Bereitstellung erstellt wurden, und sie generieren die erforderlichen DbSyncAdapter-Objekte automatisch. Dadurch wird der Code, der zum Synchronisieren von Daten mit diesen Anbietern erforderlich ist, wesentlich verringert.

In der folgenden Tabelle sind die Klassen aufgeführt, die zur Einrichtung von Datenbanken und Anbietern verwendet werden.

SQL Server SQL Server Compact Beschreibung

DbSyncScopeDescription

DbSyncScopeDescription

Stellt einen Synchronisierungsbereich dar. Dabei handelt es sich um eine logische Gruppierung von Tabellen die als Einheit synchronisiert werden.

SqlSyncScopeProvisioning

SqlCeSyncScopeProvisioning

Stellt die Bereitstellung einer SQL Server- oder SQL Server Compact-Datenbank für einen bestimmten Bereich dar, der durch ein DbSyncScopeDescription-Objekt dargestellt wird.

SqlSyncProviderScopeConfiguration

SqlCeSyncProviderScopeConfiguration

Stellt Konfigurationsinformationen dar, die von SqlSyncProvider oder SqlCeSyncProvider für einen bestimmten Bereich verwendet werden.

DbSyncTableDescription

DbSyncTableDescription

Stellt das Schema einer Tabelle dar, die Teil eines Synchronisierungsbereichs ist.

DbSyncColumnDescription

DbSyncColumnDescription

Stellt die Eigenschaften einer Spalte dar, die Teil einer in einem Synchronisierungsbereich enthaltenen Tabelle ist.

SqlSyncDescriptionBuilder

SqlCeSyncDescriptionBuilder

Stellt Bereichs- und Tabelleninformationen für eine SQL Server- oder SQL Server Compact-Datenbank dar, die an der Synchronisierung beteiligt ist. Damit werden Description-Objekte aus einer SQL Server- oder SQL Server Compact- Datenbank extrahiert.

SqlSyncTableProvisioning

SqlSyncTableProvisioning

Stellt die Bereitstellung einer SQL Server- oder SQL Server Compact-Datenbanktabelle (mit optionalen Filtern) dar, die wiederum durch ein DbSyncTableDescription-Objekt dargestellt wird.

SqlSyncProviderAdapterConfiguration

SqlSyncProviderAdapterConfiguration

Stellt Konfigurationsinformationen des Synchronisierungsadapters für eine Tabelle in einer SQL Server- oder SQL Server Compact-Datenbank dar.

Zusätzlich zu diesen Haupttypen gibt es vier weitere wichtige Typen:

Grundlegendes zu Bereichen

Hinweis

Dieser Abschnitt des Themas enthält weitere Informationen zu Synchronisierungsbereichen. Sie können auch direkt mit dem Abschnitt „Codebeispiele“ fortfahren. Sie sollten diesen Abschnitt jedoch lesen, wenn Sie gefilterte Bereiche oder mehrere Bereiche in einer Anwendung verwenden möchten.

Es ist wichtig zu verstehen, dass ein Bereich die Kombination aus Tabellen und Filtern ist. So können Sie z. B. den gefilterten Bereich sales-WA definieren, der nur die Umsatzdaten für den Staat Washington aus der customer_sales-Tabelle enthält. Wenn Sie in derselben Tabelle, z. B. sales-OR, einen weiteren Filter definieren, ist dies ein anderer Bereich. Beachten Sie beim Definieren von Filtern, dass Sync Framework Zeilen nicht automatisch löscht, die eine Filterbedingung nicht mehr erfüllen. Wenn beispielsweise ein Benutzer oder eine Anwendung einen Wert in einer Spalte aktualisiert, die zur 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. Diese Situation muss von Ihrer Anwendung behandelt werden.

Bereiche können eigenständig sein oder sich überlappen. 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.

Codebeispiele

Die Codebeispiele in diesem Abschnitt enthalten viele der zuvor beschriebenen Objekte und decken die folgenden Bereiche ab:

  • Beschreiben des Bereichs und der Tabellen

  • Bereitstellen des Servers

  • Bereitstellen der Clients

  • Festlegen der Synchronisierungsoptionen

  • Synchronisieren der Knoten

Nachdem die einzelnen Bereiche behandelt wurden, wird eine vollständige Konsolenanwendung bereitgestellt, bei der die einzelnen Beispiele mit zusätzlichem Code kombiniert werden, um eine Topologie mit vier Knoten zu synchronisieren. Die Topologie besteht aus einem SQL Server-Server, einem SQL Server-Client und zwei SQL Server Compact-Clients.

Beschreiben des Bereichs und der Tabellen

Im folgenden Codebeispiel wird ein Bereich mit dem Namen filtered_customer beschrieben, dem zwei Tabellen hinzugefügt werden: Customer und CustomerContact. Die Tabellen sind bereits in der Serverdatenbank vorhanden. Deshalb wird die GetDescriptionForTable-Methode verwendet, um das Schema aus der Serverdatenbank abzurufen. Aus der Customer-Tabelle sind alle Spalten enthalten, aus der CustomerContact-Tabelle jedoch nur zwei Spalten.

DbSyncScopeDescription scopeDesc = new DbSyncScopeDescription("filtered_customer");

// Definition for Customer.
DbSyncTableDescription customerDescription =
    SqlSyncDescriptionBuilder.GetDescriptionForTable("Sales.Customer", serverConn);

scopeDesc.Tables.Add(customerDescription);

// Definition for CustomerContact, including the list of columns to include.
Collection<string> columnsToInclude = new Collection<string>();
columnsToInclude.Add("CustomerId");
columnsToInclude.Add("PhoneType");
DbSyncTableDescription customerContactDescription =
    SqlSyncDescriptionBuilder.GetDescriptionForTable("Sales.CustomerContact", columnsToInclude, serverConn);

scopeDesc.Tables.Add(customerContactDescription);
Dim scopeDesc As New DbSyncScopeDescription("filtered_customer")

' Definition for Customer. 
Dim customerDescription As DbSyncTableDescription = _
    SqlSyncDescriptionBuilder.GetDescriptionForTable("Sales.Customer", serverConn)

scopeDesc.Tables.Add(customerDescription)


' Definition for CustomerContact, including the list of columns to include. 
Dim columnsToInclude As New Collection(Of String)()
columnsToInclude.Add("CustomerId")
columnsToInclude.Add("PhoneType")
Dim customerContactDescription As DbSyncTableDescription = _
    SqlSyncDescriptionBuilder.GetDescriptionForTable("Sales.CustomerContact", columnsToInclude, serverConn)

scopeDesc.Tables.Add(customerContactDescription)

Bereitstellen des Servers

Im folgenden Codebeispiel wird ein Bereitstellungsobjekt für den filtered_customer-Bereich erstellt, es wird angegeben, dass die Basistabellen nicht in der Serverdatenbank erstellt werden sollen und dass synchronisierungsbezogene Objekte in einem Datenbankschema mit dem Namen "Sync" erstellt werden sollen. Als Teil der Bereitstellung des Bereichs wird mit dem Code ein Filter für die Customer-Tabelle definiert. Nur Zeilen, die mit dem Filter übereinstimmen, werden synchronisiert. Für die CustomerContact-Tabelle wird kein Filter definiert. Dadurch werden alle Zeilen aus dieser Tabelle synchronisiert. Nachdem die Bereitstellungsoptionen definiert wurden, wird die Apply-Methode aufgerufen, um die Infrastruktur für die Änderungsnachverfolgung in der Serverdatenbank zu erstellen, und das Bereitstellungsskript wird in eine Datei geschrieben.

SqlSyncScopeProvisioning serverConfig = new SqlSyncScopeProvisioning(scopeDesc);
serverConfig.SetCreateTableDefault(DbSyncCreationOption.Skip);
serverConfig.ObjectSchema = "Sync";

// Specify which column(s) in the Customer table to use for filtering data, 
// and the filtering clause to use against the tracking table.
// "[side]" is an alias for the tracking table.
serverConfig.Tables["Sales.Customer"].AddFilterColumn("CustomerType");
serverConfig.Tables["Sales.Customer"].FilterClause = "[side].[CustomerType] = 'Retail'";

// Configure the scope and change-tracking infrastructure.
serverConfig.Apply(serverConn);

// Write the configuration script to a file. You can modify 
// this script if necessary and run it against the server
// to customize behavior.
File.WriteAllText("SampleConfigScript.txt",
    serverConfig.Script("SyncSamplesDb_SqlPeer1"));
Dim serverConfig As New SqlSyncScopeProvisioning(scopeDesc)
serverConfig.SetCreateTableDefault(DbSyncCreationOption.Skip)
serverConfig.ObjectSchema = "Sync"

' Specify which column(s) in the Customer table to use for filtering data, 
' and the filtering clause to use against the tracking table. 
' "[side]" is an alias for the tracking table. 
serverConfig.Tables("Sales.Customer").AddFilterColumn("CustomerType")
serverConfig.Tables("Sales.Customer").FilterClause = "[side].[CustomerType] = 'Retail'"

' Configure the scope and change-tracking infrastructure. 
serverConfig.Apply(serverConn)

' Write the configuration script to a file. You can modify 
' this script if necessary and run it against the server 
' to customize behavior. 
File.WriteAllText("SampleConfigScript.txt", serverConfig.Script("SyncSamplesDb_SqlPeer1"))

Bereitstellen der Clients

In dieser Anwendung werden Clients auf zwei verschiedene Arten bereitgestellt:

  • Die vollständige Initialisierung einer SQL Server- oder SQL Server Compact-Clientdatenbank anhand von Bereichsinformationen, die vom Server oder von einer anderen Clientdatenbank abgerufen werden.

    Anhand der von den SqlSyncDescriptionBuilder-Objekten und SqlCeSyncDescriptionBuilder-Objekten bereitgestellten Schemainformationen werden Benutzerobjekte und Synchronisierungsobjekte erstellt. Während der ersten Synchronisierungssitzung wird die Clientdatenbank für die Synchronisierung vorbereitet und alle Zeilen werden als inkrementelle Einfügungen in die Clientdatenbank heruntergeladen.

  • Momentaufnahmeninitialisierung einer SQL Server Compact-Clientdatenbank mithilfe einer bereits vorhandenen Clientdatenbank.

    Die Momentaufnahmeninitialisierung dient zur Verkürzung der Zeitspanne für das Initialisieren einer Clientdatenbank. Nachdem eine Clientdatenbank mithilfe einer vollständigen Initialisierung initialisiert wurde, können weitere Datenbanken mithilfe einer Momentaufnahme dieser ersten Clientdatenbank initialisiert werden. Bei einer Momentaufnahme handelt es sich um eine entsprechend vorbereitete SQL Server Compact-Datenbank, die Tabellenschemas, Daten (optional) und die Infrastruktur für die Änderungsnachverfolgung enthält. Kopieren Sie diese Momentaufnahme auf alle Clients, die diese benötigen. Bei der ersten Synchronisierungssitzung für einen Client werden clientspezifische Metadaten aktualisiert und alle seit dem Erstellen der Momentaufnahme aufgetretenen Änderungen in die Clientdatenbank heruntergeladen.

Wichtig

Momentaufnahmen sollten nur erzeugt werden, wenn die SQL Server Compact-Datenbank keine Aktivität aufweist. Gleichzeitige Vorgänge jedweder Art werden bei der Momentaufnahmenerstellung nicht unterstützt.

Im folgenden Codebeispiel werden zunächst Bereichsinformationen vom Server abgerufen. Die abgerufenen Schemas von Basistabelle und Änderungsnachverfolgung werden verwendet, um eine SQL Server Compact-Clientdatenbank bereitzustellen. Anschließend stellt der Code auf Grundlage der Bereichsinformationen aus der SQL Server Compact-Clientdatenbank eine SQL Server-Clientdatenbank bereit.

// Create a SQL Server Compact database and provision it based on scope
// information that is retrieved from the server. Compact databases
// do not support separate schemas, so we prefix the name of all 
// synchronization-related objects with "Sync" so that they are easy to
// identify.
Utility.DeleteAndRecreateCompactDatabase(Utility.ConnStr_SqlCeSync1, true);
Utility.DeleteAndRecreateCompactDatabase(Utility.ConnStr_SqlCeSync2, false);
DbSyncScopeDescription clientSqlCe1Desc = SqlSyncDescriptionBuilder.GetDescriptionForScope("filtered_customer", null, "Sync", serverConn);
SqlCeSyncScopeProvisioning clientSqlCe1Config = new SqlCeSyncScopeProvisioning(clientSqlCe1Desc);
clientSqlCe1Config.ObjectPrefix = "Sync";
clientSqlCe1Config.Apply(clientSqlCe1Conn);

// Provision the existing database SyncSamplesDb_SqlPeer2 based on scope
// information that is retrieved from the SQL Server Compact database. We could
// have also retrieved this information from the server.
DbSyncScopeDescription clientSqlDesc = SqlCeSyncDescriptionBuilder.GetDescriptionForScope("filtered_customer", "Sync", clientSqlCe1Conn);
SqlSyncScopeProvisioning clientSqlConfig = new SqlSyncScopeProvisioning(clientSqlDesc);
clientSqlConfig.ObjectSchema = "Sync";
clientSqlConfig.Apply(clientSqlConn);
' Create a SQL Server Compact database and provision it based on scope 
' information that is retrieved from the server. Compact databases 
' do not support separate schemas, so we prefix the name of all 
' synchronization-related objects with "Sync" so that they are easy to 
' identify. 
Utility.DeleteAndRecreateCompactDatabase(Utility.ConnStr_SqlCeSync1, True)
Utility.DeleteAndRecreateCompactDatabase(Utility.ConnStr_SqlCeSync2, False)
Dim clientSqlCe1Desc As DbSyncScopeDescription = _
    SqlSyncDescriptionBuilder.GetDescriptionForScope("filtered_customer", Nothing, "Sync", serverConn)
Dim clientSqlCe1Config As New SqlCeSyncScopeProvisioning(clientSqlCe1Desc)
clientSqlCe1Config.ObjectPrefix = "Sync"
clientSqlCe1Config.Apply(clientSqlCe1Conn)


' Provision the existing database SyncSamplesDb_SqlPeer2 based on scope 
' information that is retrieved from the SQL Server Compact database. We could 
' have also retrieved this information from the server. 
Dim clientSqlDesc As DbSyncScopeDescription = _
    SqlCeSyncDescriptionBuilder.GetDescriptionForScope("filtered_customer", "Sync", clientSqlCe1Conn)
Dim clientSqlConfig As New SqlSyncScopeProvisioning(clientSqlDesc)
clientSqlConfig.ObjectSchema = "Sync"
clientSqlConfig.Apply(clientSqlConn)

Im folgenden Codebeispiel wird anhand der SyncSampleClient1.sdf-Datenbank eine Momentaufnahme mit dem Namen SyncSampleClient2.sdf erstellt. Dann synchronisiert der Code SyncSampleClient2.sdf mit der Serverdatenbank.

// Create a snapshot from the SQL Server Compact database, which will be used to
// initialize a second Compact database. Again, this database could be provisioned
// by retrieving scope information from another database, but we want to 
// demonstrate the use of snapshots, which provide a convenient deployment
// mechanism for Compact databases.
SqlCeSyncStoreSnapshotInitialization syncStoreSnapshot = new SqlCeSyncStoreSnapshotInitialization("Sync");
syncStoreSnapshot.GenerateSnapshot(clientSqlCe1Conn, "SyncSampleClient2.sdf");

// The new SQL Server Compact client synchronizes with the server, but
// no data is downloaded because the snapshot already contains 
// all of the data from the first Compact database.
syncOrchestrator = new SampleSyncOrchestrator(
    new SqlSyncProvider("filtered_customer", serverConn, null, "Sync"),
    new SqlCeSyncProvider("filtered_customer", clientSqlCe2Conn, "Sync")
    );
syncStats = syncOrchestrator.Synchronize();
syncOrchestrator.DisplayStats(syncStats, "initial");
' Create a snapshot from the SQL Server Compact database, which will be used to 
' initialize a second Compact database. Again, this database could be provisioned 
' by retrieving scope information from another database, but we want to 
' demonstrate the use of snapshots, which provide a convenient deployment 
' mechanism for Compact databases. 
Dim syncStoreSnapshot As New SqlCeSyncStoreSnapshotInitialization("Sync")
syncStoreSnapshot.GenerateSnapshot(clientSqlCe1Conn, "SyncSampleClient2.sdf")

' The new SQL Server Compact client synchronizes with the server, but 
' no data is downloaded because the snapshot already contains 
' all of the data from the first Compact database. 
syncOrchestrator = New SampleSyncOrchestrator( _
    New SqlSyncProvider("filtered_customer", serverConn, Nothing, "Sync"), _
    New SqlCeSyncProvider("filtered_customer", clientSqlCe2Conn, "Sync"))
syncStats = syncOrchestrator.Synchronize()
syncOrchestrator.DisplayStats(syncStats, "initial")

Festlegen der Synchronisierungsoptionen

Bei dem folgenden Codebeispiel handelt es sich um einen Konstruktor aus der SampleSyncOrchestrator-Klasse in der Anwendung. Der Konstruktor nimmt zwei RelationalSyncProvider-Objekte an, da SqlSyncProvider und SqlCeSyncProvider von RelationalSyncProvider abgeleitet werden. Anschließend wird durch den Code festgelegt, welcher Anbieter der lokale Anbieter und welcher der Remoteanbieter ist. Schließlich wird festgelegt, dass Änderungen zunächst von der Remotedatenbank auf die lokale Datenbank hochgeladen und anschließend in die andere Richtung heruntergeladen werden.

public SampleSyncOrchestrator(RelationalSyncProvider localProvider, RelationalSyncProvider remoteProvider)
{

    this.LocalProvider = localProvider;
    this.RemoteProvider = remoteProvider;
    this.Direction = SyncDirectionOrder.UploadAndDownload;
}
Public Sub New(ByVal localProvider As RelationalSyncProvider, ByVal remoteProvider As RelationalSyncProvider)

    Me.LocalProvider = localProvider
    Me.RemoteProvider = remoteProvider
    Me.Direction = SyncDirectionOrder.UploadAndDownload
End Sub

Synchronisieren der Knoten

Im folgenden Codebeispiel werden Anbieter für drei verschiedene Synchronisierungssitzungen instanziiert: zwischen dem Server und dem SQL Server-Client, zwischen dem SQL Server-Client und einem der SQL Server Compact-Clients sowie zwischen dem Server und dem anderen SQL Server Compact-Client. Sieben Zeilen werden bei den ersten beiden Sitzungen synchronisiert: alle vier Zeilen von CustomerContact sowie die drei Zeilen von Customer, die die Filterkriterien erfüllen. In der dritten Sitzung werden keine Zeilen synchronisiert, da die Momentaufnahme bereits alle Daten aus der ersten SQL Server Compact-Datenbank enthält. Die Anwendung zeigt Statistiken an, die von der Synchronize()-Methode zurückgegeben werden.

SampleSyncOrchestrator syncOrchestrator;
SyncOperationStatistics syncStats;

// Data is downloaded from the server to the SQL Server client.
syncOrchestrator = new SampleSyncOrchestrator(
    new SqlSyncProvider("filtered_customer", clientSqlConn, null, "Sync"),
    new SqlSyncProvider("filtered_customer", serverConn, null, "Sync")
    );
syncStats = syncOrchestrator.Synchronize();
syncOrchestrator.DisplayStats(syncStats, "initial");

// Data is downloaded from the SQL Server client to the 
// first SQL Server Compact client.
syncOrchestrator = new SampleSyncOrchestrator(
    new SqlCeSyncProvider("filtered_customer", clientSqlCe1Conn, "Sync"),
    new SqlSyncProvider("filtered_customer", clientSqlConn, null, "Sync")
    );
syncStats = syncOrchestrator.Synchronize();
syncOrchestrator.DisplayStats(syncStats, "initial");

// Create a snapshot from the SQL Server Compact database, which will be used to
// initialize a second Compact database. Again, this database could be provisioned
// by retrieving scope information from another database, but we want to 
// demonstrate the use of snapshots, which provide a convenient deployment
// mechanism for Compact databases.
SqlCeSyncStoreSnapshotInitialization syncStoreSnapshot = new SqlCeSyncStoreSnapshotInitialization("Sync");
syncStoreSnapshot.GenerateSnapshot(clientSqlCe1Conn, "SyncSampleClient2.sdf");

// The new SQL Server Compact client synchronizes with the server, but
// no data is downloaded because the snapshot already contains 
// all of the data from the first Compact database.
syncOrchestrator = new SampleSyncOrchestrator(
    new SqlSyncProvider("filtered_customer", serverConn, null, "Sync"),
    new SqlCeSyncProvider("filtered_customer", clientSqlCe2Conn, "Sync")
    );
syncStats = syncOrchestrator.Synchronize();
syncOrchestrator.DisplayStats(syncStats, "initial");
Dim syncOrchestrator As SampleSyncOrchestrator
Dim syncStats As SyncOperationStatistics

' Data is downloaded from the server to the SQL Server client. 
syncOrchestrator = New SampleSyncOrchestrator( _
    New SqlSyncProvider("filtered_customer", clientSqlConn, Nothing, "Sync"), _
    New SqlSyncProvider("filtered_customer", serverConn, Nothing, "Sync"))
syncStats = syncOrchestrator.Synchronize()
syncOrchestrator.DisplayStats(syncStats, "initial")

' Data is downloaded from the SQL Server client to the 
' first SQL Server Compact client. 
syncOrchestrator = New SampleSyncOrchestrator( _
    New SqlCeSyncProvider("filtered_customer", clientSqlCe1Conn, "Sync"), _
    New SqlSyncProvider("filtered_customer", clientSqlConn, Nothing, "Sync"))
syncStats = syncOrchestrator.Synchronize()
syncOrchestrator.DisplayStats(syncStats, "initial")

' Create a snapshot from the SQL Server Compact database, which will be used to 
' initialize a second Compact database. Again, this database could be provisioned 
' by retrieving scope information from another database, but we want to 
' demonstrate the use of snapshots, which provide a convenient deployment 
' mechanism for Compact databases. 
Dim syncStoreSnapshot As New SqlCeSyncStoreSnapshotInitialization("Sync")
syncStoreSnapshot.GenerateSnapshot(clientSqlCe1Conn, "SyncSampleClient2.sdf")

' The new SQL Server Compact client synchronizes with the server, but 
' no data is downloaded because the snapshot already contains 
' all of the data from the first Compact database. 
syncOrchestrator = New SampleSyncOrchestrator( _
    New SqlSyncProvider("filtered_customer", serverConn, Nothing, "Sync"), _
    New SqlCeSyncProvider("filtered_customer", clientSqlCe2Conn, "Sync"))
syncStats = syncOrchestrator.Synchronize()
syncOrchestrator.DisplayStats(syncStats, "initial")

Vollständiges Codebeispiel

Das folgende vollständige Codebeispiel enthält die Codebeispiele, die weiter oben in diesem Thema beschrieben wurden, sowie zusätzlichen Code zum Anzeigen der Synchronisierungsstatistik und der Ereignisinformationen. Für das Beispiel wird die in 'Utility'-Klasse für Datenbankanbieter - Themen zur Vorgehensweise enthaltene Utility-Klasse benötigt.

using System;
using System.Collections.ObjectModel;
using System.IO;
using System.Text;
using System.Data;
using System.Data.SqlClient;
using System.Data.SqlServerCe;
using Microsoft.Synchronization;
using Microsoft.Synchronization.Data;
using Microsoft.Synchronization.Data.SqlServer;
using Microsoft.Synchronization.Data.SqlServerCe;

namespace Microsoft.Samples.Synchronization
{
    class Program
    {
        static void Main(string[] args)
        {

            // Create the connections over which provisioning and synchronization
            // are performed. The Utility class handles all functionality that is not
            // directly related to synchronization, such as holding connection 
            // string information and making changes to the server database.
            SqlConnection serverConn = new SqlConnection(Utility.ConnStr_SqlSync_Server);
            SqlConnection clientSqlConn = new SqlConnection(Utility.ConnStr_SqlSync_Client);
            SqlCeConnection clientSqlCe1Conn = new SqlCeConnection(Utility.ConnStr_SqlCeSync1);
            SqlCeConnection clientSqlCe2Conn = new SqlCeConnection(Utility.ConnStr_SqlCeSync2);

            // Create a scope named "filtered_customer", and add two tables to the scope.
            // GetDescriptionForTable gets the schema of each table, so that tracking 
            // tables and triggers can be created for that table. For Customer, we add
            // the entire table. For CustomerContact, we add only two of the columns.
            DbSyncScopeDescription scopeDesc = new DbSyncScopeDescription("filtered_customer");

            // Definition for Customer.
            DbSyncTableDescription customerDescription =
                SqlSyncDescriptionBuilder.GetDescriptionForTable("Sales.Customer", serverConn);

            scopeDesc.Tables.Add(customerDescription);

            // Definition for CustomerContact, including the list of columns to include.
            Collection<string> columnsToInclude = new Collection<string>();
            columnsToInclude.Add("CustomerId");
            columnsToInclude.Add("PhoneType");
            DbSyncTableDescription customerContactDescription =
                SqlSyncDescriptionBuilder.GetDescriptionForTable("Sales.CustomerContact", columnsToInclude, serverConn);

            scopeDesc.Tables.Add(customerContactDescription);

            // Create a provisioning object for "filtered_customer". We specify that
            // base tables should not be created (They already exist in SyncSamplesDb_SqlPeer1),
            // and that all synchronization-related objects should be created in a 
            // database schema named "Sync". If you specify a schema, it must already exist
            // in the database.
            SqlSyncScopeProvisioning serverConfig = new SqlSyncScopeProvisioning(scopeDesc);
            serverConfig.SetCreateTableDefault(DbSyncCreationOption.Skip);
            serverConfig.ObjectSchema = "Sync";

            // Specify which column(s) in the Customer table to use for filtering data, 
            // and the filtering clause to use against the tracking table.
            // "[side]" is an alias for the tracking table.
            serverConfig.Tables["Sales.Customer"].AddFilterColumn("CustomerType");
            serverConfig.Tables["Sales.Customer"].FilterClause = "[side].[CustomerType] = 'Retail'";

            // Configure the scope and change-tracking infrastructure.
            serverConfig.Apply(serverConn);

            // Write the configuration script to a file. You can modify 
            // this script if necessary and run it against the server
            // to customize behavior.
            File.WriteAllText("SampleConfigScript.txt",
                serverConfig.Script("SyncSamplesDb_SqlPeer1"));


            // Provision each of the client databases.           

            // Create a SQL Server Compact database and provision it based on scope
            // information that is retrieved from the server. Compact databases
            // do not support separate schemas, so we prefix the name of all 
            // synchronization-related objects with "Sync" so that they are easy to
            // identify.
            Utility.DeleteAndRecreateCompactDatabase(Utility.ConnStr_SqlCeSync1, true);
            Utility.DeleteAndRecreateCompactDatabase(Utility.ConnStr_SqlCeSync2, false);
            DbSyncScopeDescription clientSqlCe1Desc = SqlSyncDescriptionBuilder.GetDescriptionForScope("filtered_customer", null, "Sync", serverConn);
            SqlCeSyncScopeProvisioning clientSqlCe1Config = new SqlCeSyncScopeProvisioning(clientSqlCe1Desc);
            clientSqlCe1Config.ObjectPrefix = "Sync";
            clientSqlCe1Config.Apply(clientSqlCe1Conn);

            // Provision the existing database SyncSamplesDb_SqlPeer2 based on scope
            // information that is retrieved from the SQL Server Compact database. We could
            // have also retrieved this information from the server.
            DbSyncScopeDescription clientSqlDesc = SqlCeSyncDescriptionBuilder.GetDescriptionForScope("filtered_customer", "Sync", clientSqlCe1Conn);
            SqlSyncScopeProvisioning clientSqlConfig = new SqlSyncScopeProvisioning(clientSqlDesc);
            clientSqlConfig.ObjectSchema = "Sync";
            clientSqlConfig.Apply(clientSqlConn);


            // Initial synchronization sessions. 7 rows are synchronized:
            // all rows (4) from CustomerContact, and the 3 rows from Customer 
            // that satisfy the filtering criteria.
            SampleSyncOrchestrator syncOrchestrator;
            SyncOperationStatistics syncStats;

            // Data is downloaded from the server to the SQL Server client.
            syncOrchestrator = new SampleSyncOrchestrator(
                new SqlSyncProvider("filtered_customer", clientSqlConn, null, "Sync"),
                new SqlSyncProvider("filtered_customer", serverConn, null, "Sync")
                );
            syncStats = syncOrchestrator.Synchronize();
            syncOrchestrator.DisplayStats(syncStats, "initial");

            // Data is downloaded from the SQL Server client to the 
            // first SQL Server Compact client.
            syncOrchestrator = new SampleSyncOrchestrator(
                new SqlCeSyncProvider("filtered_customer", clientSqlCe1Conn, "Sync"),
                new SqlSyncProvider("filtered_customer", clientSqlConn, null, "Sync")
                );
            syncStats = syncOrchestrator.Synchronize();
            syncOrchestrator.DisplayStats(syncStats, "initial");

            // Create a snapshot from the SQL Server Compact database, which will be used to
            // initialize a second Compact database. Again, this database could be provisioned
            // by retrieving scope information from another database, but we want to 
            // demonstrate the use of snapshots, which provide a convenient deployment
            // mechanism for Compact databases.
            SqlCeSyncStoreSnapshotInitialization syncStoreSnapshot = new SqlCeSyncStoreSnapshotInitialization("Sync");
            syncStoreSnapshot.GenerateSnapshot(clientSqlCe1Conn, "SyncSampleClient2.sdf");

            // The new SQL Server Compact client synchronizes with the server, but
            // no data is downloaded because the snapshot already contains 
            // all of the data from the first Compact database.
            syncOrchestrator = new SampleSyncOrchestrator(
                new SqlSyncProvider("filtered_customer", serverConn, null, "Sync"),
                new SqlCeSyncProvider("filtered_customer", clientSqlCe2Conn, "Sync")
                );
            syncStats = syncOrchestrator.Synchronize();
            syncOrchestrator.DisplayStats(syncStats, "initial");


            // Make changes on the server: 1 insert, 1 update, and 1 delete.
            Utility.MakeDataChangesOnNode(Utility.ConnStr_SqlSync_Server, "Customer");

            // Synchronize again. Three changes were made on the server, but
            // only two of them applied to rows that are in the "filtered_customer"
            // scope. The other row is not synchronized.
            // Notice that the order of synchronization is different from the initial
            // sessions, but the two changes are propagated to all nodes.
            syncOrchestrator = new SampleSyncOrchestrator(
                new SqlCeSyncProvider("filtered_customer", clientSqlCe1Conn, "Sync"),
                new SqlSyncProvider("filtered_customer", serverConn, null, "Sync")
                );
            syncStats = syncOrchestrator.Synchronize();
            syncOrchestrator.DisplayStats(syncStats, "subsequent");

            syncOrchestrator = new SampleSyncOrchestrator(
                new SqlSyncProvider("filtered_customer", clientSqlConn, null, "Sync"),
                new SqlCeSyncProvider("filtered_customer", clientSqlCe1Conn, "Sync")
            );
            syncStats = syncOrchestrator.Synchronize();
            syncOrchestrator.DisplayStats(syncStats, "subsequent");

            syncOrchestrator = new SampleSyncOrchestrator(
                new SqlCeSyncProvider("filtered_customer", clientSqlCe2Conn, "Sync"),
                new SqlSyncProvider("filtered_customer", clientSqlConn, null, "Sync")
            );
            syncStats = syncOrchestrator.Synchronize();
            syncOrchestrator.DisplayStats(syncStats, "subsequent");

            serverConn.Close();
            serverConn.Dispose();
            clientSqlConn.Close();
            clientSqlConn.Dispose();
            clientSqlCe1Conn.Close();
            clientSqlCe1Conn.Dispose();
            clientSqlCe2Conn.Close();
            clientSqlCe2Conn.Dispose();

            Utility.CleanUpSqlNode(Utility.ConnStr_SqlSync_Server);
            Utility.CleanUpSqlNode(Utility.ConnStr_SqlSync_Client);

            Console.Write("\nPress any key to exit.");
            Console.Read();

        }

    }

    public class SampleSyncOrchestrator : SyncOrchestrator
    {
        public SampleSyncOrchestrator(RelationalSyncProvider localProvider, RelationalSyncProvider remoteProvider)
        {

            this.LocalProvider = localProvider;
            this.RemoteProvider = remoteProvider;
            this.Direction = SyncDirectionOrder.UploadAndDownload;
        }

        public void DisplayStats(SyncOperationStatistics syncStatistics, string syncType)
        {
            Console.WriteLine(String.Empty);
            if (syncType == "initial")
            {
                Console.WriteLine("****** Initial Synchronization ******");
            }
            else if (syncType == "subsequent")
            {
                Console.WriteLine("***** Subsequent Synchronization ****");
            }

            Console.WriteLine("Start Time: " + syncStatistics.SyncStartTime);
            Console.WriteLine("Total Changes Uploaded: " + syncStatistics.UploadChangesTotal);
            Console.WriteLine("Total Changes Downloaded: " + syncStatistics.DownloadChangesTotal);
            Console.WriteLine("Complete Time: " + syncStatistics.SyncEndTime);
            Console.WriteLine(String.Empty);
        }
    }
}
Imports System
Imports System.Collections.ObjectModel
Imports System.IO
Imports System.Text
Imports System.Data
Imports System.Data.SqlClient
Imports System.Data.SqlServerCe
Imports Microsoft.Synchronization
Imports Microsoft.Synchronization.Data
Imports Microsoft.Synchronization.Data.SqlServer
Imports Microsoft.Synchronization.Data.SqlServerCe

Namespace Microsoft.Samples.Synchronization

    Class Program

        Public Shared Sub Main(ByVal args As String())

            ' Create the connections over which provisioning and synchronization 
            ' are performed. The Utility class handles all functionality that is not 
            ' directly related to synchronization, such as holding connection 
            ' string information and making changes to the server database. 
            Dim serverConn As New SqlConnection(Utility.ConnStr_SqlSync_Server)
            Dim clientSqlConn As New SqlConnection(Utility.ConnStr_SqlSync_Client)
            Dim clientSqlCe1Conn As New SqlCeConnection(Utility.ConnStr_SqlCeSync1)
            Dim clientSqlCe2Conn As New SqlCeConnection(Utility.ConnStr_SqlCeSync2)

            ' Create a scope named "filtered_customer", and add two tables to the scope. 
            ' GetDescriptionForTable gets the schema of each table, so that tracking 
            ' tables and triggers can be created for that table. For Customer, we add 
            ' the entire table. For CustomerContact, we add only two of the columns. 
            Dim scopeDesc As New DbSyncScopeDescription("filtered_customer")

            ' Definition for Customer. 
            Dim customerDescription As DbSyncTableDescription = _
                SqlSyncDescriptionBuilder.GetDescriptionForTable("Sales.Customer", serverConn)

            scopeDesc.Tables.Add(customerDescription)


            ' Definition for CustomerContact, including the list of columns to include. 
            Dim columnsToInclude As New Collection(Of String)()
            columnsToInclude.Add("CustomerId")
            columnsToInclude.Add("PhoneType")
            Dim customerContactDescription As DbSyncTableDescription = _
                SqlSyncDescriptionBuilder.GetDescriptionForTable("Sales.CustomerContact", columnsToInclude, serverConn)

            scopeDesc.Tables.Add(customerContactDescription)

            ' Create a provisioning object for "filtered_customer". We specify that 
            ' base tables should not be created (They already exist in SyncSamplesDb_SqlPeer1), 
            ' and that all synchronization-related objects should be created in a 
            ' database schema named "Sync". If you specify a schema, it must already exist 
            ' in the database. 
            Dim serverConfig As New SqlSyncScopeProvisioning(scopeDesc)
            serverConfig.SetCreateTableDefault(DbSyncCreationOption.Skip)
            serverConfig.ObjectSchema = "Sync"

            ' Specify which column(s) in the Customer table to use for filtering data, 
            ' and the filtering clause to use against the tracking table. 
            ' "[side]" is an alias for the tracking table. 
            serverConfig.Tables("Sales.Customer").AddFilterColumn("CustomerType")
            serverConfig.Tables("Sales.Customer").FilterClause = "[side].[CustomerType] = 'Retail'"

            ' Configure the scope and change-tracking infrastructure. 
            serverConfig.Apply(serverConn)

            ' Write the configuration script to a file. You can modify 
            ' this script if necessary and run it against the server 
            ' to customize behavior. 
            File.WriteAllText("SampleConfigScript.txt", serverConfig.Script("SyncSamplesDb_SqlPeer1"))


            ' Provision each of the client databases. 

            ' Create a SQL Server Compact database and provision it based on scope 
            ' information that is retrieved from the server. Compact databases 
            ' do not support separate schemas, so we prefix the name of all 
            ' synchronization-related objects with "Sync" so that they are easy to 
            ' identify. 
            Utility.DeleteAndRecreateCompactDatabase(Utility.ConnStr_SqlCeSync1, True)
            Utility.DeleteAndRecreateCompactDatabase(Utility.ConnStr_SqlCeSync2, False)
            Dim clientSqlCe1Desc As DbSyncScopeDescription = _
                SqlSyncDescriptionBuilder.GetDescriptionForScope("filtered_customer", Nothing, "Sync", serverConn)
            Dim clientSqlCe1Config As New SqlCeSyncScopeProvisioning(clientSqlCe1Desc)
            clientSqlCe1Config.ObjectPrefix = "Sync"
            clientSqlCe1Config.Apply(clientSqlCe1Conn)


            ' Provision the existing database SyncSamplesDb_SqlPeer2 based on scope 
            ' information that is retrieved from the SQL Server Compact database. We could 
            ' have also retrieved this information from the server. 
            Dim clientSqlDesc As DbSyncScopeDescription = _
                SqlCeSyncDescriptionBuilder.GetDescriptionForScope("filtered_customer", "Sync", clientSqlCe1Conn)
            Dim clientSqlConfig As New SqlSyncScopeProvisioning(clientSqlDesc)
            clientSqlConfig.ObjectSchema = "Sync"
            clientSqlConfig.Apply(clientSqlConn)


            ' Initial synchronization sessions. 7 rows are synchronized: 
            ' all rows (4) from CustomerContact, and the 3 rows from Customer 
            ' that satisfy the filtering criteria. 
            Dim syncOrchestrator As SampleSyncOrchestrator
            Dim syncStats As SyncOperationStatistics

            ' Data is downloaded from the server to the SQL Server client. 
            syncOrchestrator = New SampleSyncOrchestrator( _
                New SqlSyncProvider("filtered_customer", clientSqlConn, Nothing, "Sync"), _
                New SqlSyncProvider("filtered_customer", serverConn, Nothing, "Sync"))
            syncStats = syncOrchestrator.Synchronize()
            syncOrchestrator.DisplayStats(syncStats, "initial")

            ' Data is downloaded from the SQL Server client to the 
            ' first SQL Server Compact client. 
            syncOrchestrator = New SampleSyncOrchestrator( _
                New SqlCeSyncProvider("filtered_customer", clientSqlCe1Conn, "Sync"), _
                New SqlSyncProvider("filtered_customer", clientSqlConn, Nothing, "Sync"))
            syncStats = syncOrchestrator.Synchronize()
            syncOrchestrator.DisplayStats(syncStats, "initial")

            ' Create a snapshot from the SQL Server Compact database, which will be used to 
            ' initialize a second Compact database. Again, this database could be provisioned 
            ' by retrieving scope information from another database, but we want to 
            ' demonstrate the use of snapshots, which provide a convenient deployment 
            ' mechanism for Compact databases. 
            Dim syncStoreSnapshot As New SqlCeSyncStoreSnapshotInitialization("Sync")
            syncStoreSnapshot.GenerateSnapshot(clientSqlCe1Conn, "SyncSampleClient2.sdf")

            ' The new SQL Server Compact client synchronizes with the server, but 
            ' no data is downloaded because the snapshot already contains 
            ' all of the data from the first Compact database. 
            syncOrchestrator = New SampleSyncOrchestrator( _
                New SqlSyncProvider("filtered_customer", serverConn, Nothing, "Sync"), _
                New SqlCeSyncProvider("filtered_customer", clientSqlCe2Conn, "Sync"))
            syncStats = syncOrchestrator.Synchronize()
            syncOrchestrator.DisplayStats(syncStats, "initial")


            ' Make changes on the server: 1 insert, 1 update, and 1 delete. 
            Utility.MakeDataChangesOnNode(Utility.ConnStr_SqlSync_Server, "Customer")


            ' Synchronize again. Three changes were made on the server, but 
            ' only two of them applied to rows that are in the "filtered_customer" 
            ' scope. The other row is not synchronized. 
            ' Notice that the order of synchronization is different from the initial 
            ' sessions, but the two changes are propagated to all nodes. 

            syncOrchestrator = New SampleSyncOrchestrator( _
                New SqlCeSyncProvider("filtered_customer", clientSqlCe1Conn, "Sync"), _
                New SqlSyncProvider("filtered_customer", serverConn, Nothing, "Sync"))
            syncStats = syncOrchestrator.Synchronize()
            syncOrchestrator.DisplayStats(syncStats, "subsequent")

            syncOrchestrator = New SampleSyncOrchestrator( _
                New SqlSyncProvider("filtered_customer", clientSqlConn, Nothing, "Sync"), _
                New SqlCeSyncProvider("filtered_customer", clientSqlCe1Conn, "Sync"))
            syncStats = syncOrchestrator.Synchronize()
            syncOrchestrator.DisplayStats(syncStats, "subsequent")

            syncOrchestrator = New SampleSyncOrchestrator( _
                New SqlCeSyncProvider("filtered_customer", clientSqlCe2Conn, "Sync"), _
                New SqlSyncProvider("filtered_customer", clientSqlConn, Nothing, "Sync"))
            syncStats = syncOrchestrator.Synchronize()
            syncOrchestrator.DisplayStats(syncStats, "subsequent")


            serverConn.Close()
            serverConn.Dispose()
            clientSqlConn.Close()
            clientSqlConn.Dispose()
            clientSqlCe1Conn.Close()
            clientSqlCe1Conn.Dispose()
            clientSqlCe2Conn.Close()
            clientSqlCe2Conn.Dispose()

            Utility.CleanUpSqlNode(Utility.ConnStr_SqlSync_Server)
            Utility.CleanUpSqlNode(Utility.ConnStr_SqlSync_Client)

            Console.Write(vbLf & "Press any key to exit.")
            Console.Read()
        End Sub

    End Class

    Public Class SampleSyncOrchestrator
        Inherits SyncOrchestrator
        Public Sub New(ByVal localProvider As RelationalSyncProvider, ByVal remoteProvider As RelationalSyncProvider)

            Me.LocalProvider = localProvider
            Me.RemoteProvider = remoteProvider
            Me.Direction = SyncDirectionOrder.UploadAndDownload
        End Sub

        Public Sub DisplayStats(ByVal syncStatistics As SyncOperationStatistics, ByVal syncType As String)
            Console.WriteLine([String].Empty)
            If syncType = "initial" Then
                Console.WriteLine("****** Initial Synchronization ******")
            ElseIf syncType = "subsequent" Then
                Console.WriteLine("***** Subsequent Synchronization ****")
            End If

            Console.WriteLine("Start Time: " & syncStatistics.SyncStartTime)
            Console.WriteLine("Total Changes Uploaded: " & syncStatistics.UploadChangesTotal)
            Console.WriteLine("Total Changes Downloaded: " & syncStatistics.DownloadChangesTotal)
            Console.WriteLine("Complete Time: " & syncStatistics.SyncEndTime)
            Console.WriteLine([String].Empty)
        End Sub
    End Class
End Namespace

Siehe auch

Konzepte

Übersicht über die Synchronisierung für die Zusammenarbeit
Architektur und Klassen der Synchronisierung für die Zusammenarbeit