Hintergrund und erste Schritte mit dem SQL Azure Sync Service

[ 1 ] Februar 22, 2012 |

SQL Azure stellt ein echtes relationales Datenbankmanagementsystem als Cloud Service bereit. Enthalten sind ein Subset der Datenbank-Engine aus SQL Server, die SQL Azure Reporting Services sowie der SQL Azure Sync Service.

von Holger Sirtl

Abbildung 1: SQL Azure

Der SQL Azure Sync Service erlaubt es, eine lokale Datenbank mit einer SQL Azure Datenbank zu synchronisieren. D.h. Änderungen, die in einer der beiden beteiligten Datenbanken vorgenommen werden, können bei Bedarf in die jeweils andere Datenbank übertragen werden. Damit wird es sehr einfach möglich, Offline-Szenarien zu realisieren, in denen beim Aus-fall der Internet-Verbindung mit einer lokalen Datenbank weitergearbeitet werden kann. Änderungen, die in dieser Zeit lokal vorgenommen werden, können dann sehr leicht nach SQL Azure übertragen werden, wenn die Verbindung wieder steht.

Für die folgenden Ausführungsschritte legen Sie zunächst eine neue Datenbank unter SQL Azure an. Führen Sie auf dieser Datenbank (z.B. mit Hilfe des SQL Server Management Studios) das in Listing 1 gezeigte SQL-Skript aus.

CREATE TABLE [Kunden](
    [KundenID] [int] IDENTITY(1,1) NOT NULL PRIMARY KEY CLUSTERED,
    [Anrede] [nvarchar](6) NOT NULL,
    [Vorname] [nvarchar](50) NOT NULL,
    [Nachname] [nvarchar](50) NOT NULL,
    [Email] [nvarchar](50) NOT NULL,
    [Website] [nvarchar](50) NULL,
    [Telefon] [nvarchar](30) NULL,
    [Timestamp] [timestamp] NOT NULL
)

CREATE INDEX IX_Kunden_Email ON Kunden (Email)

INSERT INTO [Kunden]
        ([Anrede], [Vorname], [Nachname], [Email], [Website], [Telefon])
    VALUES
        ('Herr', 'Holger', 'Sirtl', 'hsirtl@microsoft.com',
         'http://blogs.msdn.com/hsirtl', '089/123-456')

Listing 1: Anlegen von Tabelle und Tabelleneintrag in SQL Azure

Damit wird die Tabelle Kunden angelegt und in dieser Tabelle ein einzelner Tabelleneintrag geschrieben. Tabelle und Inhalt sollen später mit Hilfe des Microsoft Sync Frameworks in eine lokale Datenbank übertragen werden.

Das Microsoft Sync Framework

Synchronisation zwischen SQL Azure und einer lokalen Datenbank wird mit Hilfe des Microsoft Sync Frameworks implementiert. In den folgenden Abschnitten soll eine kleine Konsolenanwendung entwickelt werden, die eine Synchronisationsbeziehung zwischen einer lokalen SQL Express Datenbank und einer SQL Azure Datenbank herstellt. Die Architektur ist in Abbildung 2 zu sehen.

Abbildung 2: Architektur einer Sync Framework basierten Lösung

Eine auf dem Sync Framework aufsetzende Lösung enthält in der Regel folgende Komponenten, die in der Architekturabbildung zu sehen sind:

  • Sync Provider
    Dies ist eine Art Datenbank-Treiber, der die Funktionen des Sync Frameworks für die beteiligten Datenbanken in die jeweiligen Datenbank-Aufrufe übersetzt. Hier muss also für die betreffende Datenbank ein passender Sync Provider eingesetzt werden. Für SQL Server und SQL Azure stellt Microsoft passende Provider bereit. Für andere Datenbanksysteme sind von den jeweiligen Herstellern ebenfalls Provider verfügbar.
  • Sync Orchestrator
    Diese Komponente konfiguriert die beteiligten Datenbanken, initiiert die Synchronisa-tion und wertet die Ergebnisse aus. Für die Kommunikation mit den Datenbanken bedient er sich der Sync Provider.

Starten Sie nun Visual Studio und legen über den Menüpunkt File / New / Project ein neues Projekt an. Wählen sie als Projektvorlage eine Konsolenanwendung (Visual C# / Windows / Console Application). Da die Anwendung das Sync Framework nutzen soll, werden vier DLLs benötigt, die in Tabelle 1 aufgelistet sind.

Datei (C:[.]Program Files[.]Microsoft Sync Framework[.]…) Namespace
2.1[.]Runtime[.]x86[.] Microsoft.Synchronization.dll Microsoft.Synchronization
2.1[.]Runtime[.]ADO.NET[.]V3.1\x86[.] Microsoft.Synchronization.Data.dll Microsoft.Synchronization.Data
2.1[.]Runtime[.]ADO.NET[.]V3.1[.]x86[.] Microsoft.Synchronization.Data.Server.dll Microsoft.Synchronization.Data.Server
2.1[.]Runtime[.]ADO.NET[.]V3.1[.]x86[.] Microsoft.Synchronization.Data.SqlServer.dll Microsoft.Synchronization.Data.SqlServer


Tabelle 1: Für das Sync Framework benötigte Dateien und Namespaces

* die [.] bitten gegen einen SLASH (SHIFT + 7) ersetzen.

Nach Hinzufügen der DLLs sollte der Solution Explorer die entsprechenden Namespaces wie in Abbildung 3 zu sehen auflisten.

Abbildung 3: Referenzen zum Sync Framework

Die Konsolenanwendung soll die folgenden zwei Funktionalitäten bieten:

  • Initialisierung der Synchronisationsbeziehung (Methode Setup())
  • Durchführung einer Synchronisation (Methode Sync())

Die beiden hierzu benötigten Methoden sind in Listing 2 zu sehen. Sie werden je nach Aufrufparameter aufgerufen. Fehlt der Aufrufparameter, wird eine entsprechende Information auf der Konsole angezeigt.

using System;
using System.Data.SqlClient;
using Microsoft.Synchronization.Data.SqlServer;
using Microsoft.Synchronization.Data;
using Microsoft.Synchronization;

namespace SyncTest
{
    class Program
    {
        public static string sqlazureConnectionString =
            @"Server=.database.windows.net;
              Database=; 
              User ID=@; 
              Password=; 
              Trusted_Connection=False; 
              Encrypt=True;"; 
        public static string sqllocalConnectionString =
            @"Server=.\SQLEXPRESS;
              Database=; 
              Trusted_Connection=True"; 

        public static readonly string scopeName = "alltablesyncgroup";

        static void Main(string[] args)
        {
            // Test if input arguments were supplied:
            if (args.Length == 0)
            {
                System.Console.WriteLine("Please enter an argument.");
                System.Console.WriteLine("Usage: SyncTest.exe -setup");
                System.Console.WriteLine("       SyncTest.exe -sync");
            }

            else if (args[0] == "-setup")
                Setup();
            else if (args[0] == "-sync")
                Sync();
        }

        public static void Setup() { ... }
        public static void Sync() { ... }

        }
    }
}

Listing 2: Code-Gerüst für die Sync Anwendung

Die beiden Connection-Strings definieren den Zugang zu den beiden beteiligten Datenbanken. Ersetzen Sie die Platzhalter durch die für Ihre Datenbanken gültigen Werte.

Konfiguration der beteiligten Datenbanken

Bevor eine Synchronisation der Datenbanken durchgeführt werden kann, müssen diese entsprechend vorbereitet werden. Dabei werden in den Datenbanken Hilfstabellen angelegt, in denen Synchronisationsinformationen gespeichert werden. Das Schema der zu synchronisierenden Tabellen bleibt dabei unverändert. Für die initiale Konfiguration der Datenbanken implementieren Sie die Setup()-Methode nun wie in Listing 3 gezeigt. Die dort durchgeführte Konfiguration setzt voraus, dass Sie die SQL Azure Datenbank aufgesetzt haben, d.h. eine Kunden-Tabelle existiert.

public static void Setup()
{
    try
    {
        SqlConnection sqlServerConn = new SqlConnection(sqllocalConnectionString);
        SqlConnection sqlAzureConn = new SqlConnection(sqlazureConnectionString);
        DbSyncScopeDescription myScope = new DbSyncScopeDescription(scopeName);

        DbSyncTableDescription Customer =
            SqlSyncDescriptionBuilder.GetDescriptionForTable("Kunden", sqlAzureConn);

        // Add the tables from above to the scope
        myScope.Tables.Add(Customer);

 // Setup SQL Server for sync
        SqlSyncScopeProvisioning sqlServerProv =
            new SqlSyncScopeProvisioning(sqlServerConn, myScope);
        if (!sqlServerProv.ScopeExists(scopeName))
        {
            // Apply the scope provisioning.
            Console.WriteLine("Provisioning SQL Server for sync " + DateTime.Now);
            sqlServerProv.Apply();
            Console.WriteLine("Done Provisioning SQL Server for sync " + DateTime.Now);
        }
        else
            Console.WriteLine("SQL Server Database server already provisioned for sync " +
                              DateTime.Now);

        // Setup SQL Azure for sync
        SqlSyncScopeProvisioning sqlAzureProv =
            new SqlSyncScopeProvisioning(sqlAzureConn, myScope);
        if (!sqlAzureProv.ScopeExists(scopeName))
        {
            // Apply the scope provisioning.
            Console.WriteLine("Provisioning SQL Azure for sync " + DateTime.Now);
            sqlAzureProv.Apply();
            Console.WriteLine("Done Provisioning SQL Azure for sync " + DateTime.Now);
        }
        else
            Console.WriteLine("SQL Azure Database server already provisioned for sync " +
                              DateTime.Now);

        sqlAzureConn.Close();
        sqlServerConn.Close();
    }
    catch (Exception ex)
    {
        Console.WriteLine(ex);
    }
}

Listing 3: Methode zum Initialisieren der Synchronisationsbeziehung

Die Methode baut zunächst Verbindungen zu den beiden Datenbanken (wie über die Connection-Strings konfiguriert) auf und initialisiert einen sogenannten Sync-Scope. Dieser legt den Bereich, d.h. die Tabellen, fest, der synchronisiert werden soll. Danach wird die Schema-Information der Kunden-Tabelle ermittelt und dem Sync-Scope hinzugefügt. Anschließend wird der Sync-Scope zunächst auf der lokalen Datenbank und dann in SQL Azure provisioniert. Abschließend werden die Verbindungen zu den Datenbanken wieder geschlossen. Bauen Sie die Solution durch Auswahl des Menüpunkts Build / Build Solution. Öffnen sie anschließend ein Konsolenfenster und wechseln dort in das Verzeichnis, in das Visual Studio die exe-Datei geschrieben hat. Abbildung 4 zeigt die Konsolenausgabe bei Ausführung der Anwendung (zuerst Aufruf ohne Parameter, dann mit Parameter-setup).

Abbildung 4: Initialisierung des Sync Frameworks

Damit ist die Initialisierung der Datenbanken abgeschlossen. Das Sync Framework hat in beiden Datenbanken Hilfstabellen angelegt, in denen Änderungen bis zur nächsten Synchronisation zwischengespeichert werden. Abbildung 5 zeigt die Tabellenansicht aus dem SQL Server Management Studio vor und nach der Initialisierung.

Abbildung 5: Tabellen vor und nach Initialisierung des Sync Frameworks

Vor der Initialisierung ist nur in SQL Azure eine Kunden-Tabelle vorhanden. Nach der Initialisierung wurde zum einen die Tabelle auch in der lokalen Datenbank angelegt (ja, dies erledigt das Sync Framework automatisch), zum anderen wurden in beiden Datenbanken die Hilfstabellen angelegt. Noch wurden allerdings keine Daten übertragen. Die Änderungen beziehen sich noch ausschließlich auf die Schemata.

Synchronisation mit einer lokalen Datenbank

Nun soll die Sync()-Methode implementiert werden, mit deren Hilfe eine Synchronisation der beiden Datenbanken, d.h. ein Datenabgleich, erfolgen kann. Implementieren Sie die Methode wie in Listing 4 gezeigt. Die Methode baut Verbindungen zu den beiden Datenbanken auf und instanziiert einen neuen Sync-Orchestrator. Im Orchestrator werden zwei passende Sync-Provider und die gewünschte Synchronisationsrichtung definiert. Im Beispiel soll die Synchronisation in beide Richtungen erfolgen.

public static void Sync()
{
    try
    {
        SqlConnection sqlServerConn = new SqlConnection(sqllocalConnectionString);
        SqlConnection sqlAzureConn = new SqlConnection(sqlazureConnectionString);
        SyncOrchestrator orch = new SyncOrchestrator
        {
            LocalProvider = new SqlSyncProvider(scopeName, sqlServerConn),
            RemoteProvider = new SqlSyncProvider(scopeName, sqlAzureConn),
            Direction = SyncDirectionOrder.UploadAndDownload
        };

        Console.WriteLine("ScopeName={0} ", scopeName);
        Console.WriteLine("Starting Sync " + DateTime.Now);

        ShowStatistics(orch.Synchronize());

        sqlAzureConn.Close();
        sqlServerConn.Close();
    }
    catch (Exception ex)
    {
        Console.WriteLine(ex);
    }
}

public static void ShowStatistics(SyncOperationStatistics syncStats)
{
  Console.WriteLine("General Sync Statistics");
  Console.WriteLine("=======================");
  Console.WriteLine("\tSync Start Time : " + syncStats.SyncStartTime.ToString());
  Console.WriteLine("\tSync End Time   : " + syncStats.SyncEndTime.ToString());
  Console.WriteLine("");
  Console.WriteLine("Upload Statistics   (local SQL -> SQL Azure)");
  Console.WriteLine("============================================");
  Console.WriteLine("\tChanges Applied : " + syncStats.UploadChangesApplied.ToString());
  Console.WriteLine("\tChanges Failed  : " + syncStats.UploadChangesFailed.ToString());
  Console.WriteLine("\tChanges Total   : " + syncStats.UploadChangesTotal.ToString());
  Console.WriteLine("");
  Console.WriteLine("Download Statistics (SQL Azure -> local SQL)");
  Console.WriteLine("============================================");
  Console.WriteLine("\tChanges Applied : " + syncStats.DownloadChangesApplied.ToString());
  Console.WriteLine("\tChanges Failed  : " + syncStats.DownloadChangesFailed.ToString());
  Console.WriteLine("\tChanges Total   : " + syncStats.DownloadChangesTotal.ToString());
}

Listing 4: Methode zum Synchronisieren der Inhalte der Datenbanken

Nach erfolgreicher Synchronisation wird das Ergebnis über die Hilfsmethode ShowStatistics() angezeigt. Bauen Sie die Solution und wechseln Sie anschließend in das Konsolenfenster. Rufen Sie dort die Anwendung mit dem Aufrufparameter -sync auf. Abbildung 6 zeigt das Ergebnis.

Abbildung 6: Synchronisation der Inhalte aus SQL Azure

Da in der SQL Azure Datenbank nur ein Eintrag vorhanden war, zeigt die Ausgabe an, dass eine Änderung von der SQL Azure Datenbank in die lokale Datenbank übertragen wurde. Prüfen Sie (z.B. im SQL Server Management Studio), ob der Eintrag nun korrekt in der lokalen Datenbank liegt.

Ändern Sie nun den Eintrag in der lokalen Datenbank. Hierzu können Sie das SQL Skript verwenden, das in Listing 5 abgebildet ist, und führen Sie dieses im SQL Server Management Studio aus.

UPDATE [LokalDB].[dbo].[Kunden]
   SET [Vorname] = 'Max'
      ,[Nachname] = 'Mustermann'
 WHERE [KundenID] = 1
GO

Listing 5: Änderung eines Eintrags in der lokalen Datenbank

Starten Sie nun einen neuen Synchronisationslauf, indem Sie wieder in das Konsolenfenster wechseln und dort durch Aufruf der Anwendung mittels SyncTest -sync eine Synchronisa-tion der Datenbanken durchführen. Das Ergebnis ist in Abbildung 7 zu sehen.

Abbildung 7: Synchronisation der Änderung der lokalen Datenbank

In diesem zweiten Synchronisationslauf wurde nun ein Eintrag (der geänderte Eintrag) von der lokalen Datenbank nach SQL Azure übertragen. Abbildung 8 zeigt, wie sich das Ergebnis im SQL Server Management Studio darstellt. Dort ist der geänderte Eintrag in SQL Azure abgebildet.

Abbildung 8: Ergebnis der Synchronisation

Ressourcen

Ressourcen zur SQL Azure Database Engine

Ressourcen zum SQL Azure Sync Service

Tags:

Category: Gastbeiträge

About the Author ()

Leave a Reply

You must be logged in to post a comment.