Vor einiger Zeit habe ich mich für die SQL Server Data Services Beta angemeldet und habe heute meinen Account zugewiesen bekommen. Obwohl ich heute eigentlich was komplett anderes machen wollte, habe ich kurzfristig beschlossen die Webcast Aufnahme für zu verschieben und mir die SSDS näher anzuschauen.

Auf der Connect Seite findet man schliesslich auch die Dokumentation zum herunterladen und kann sogleich mit dem Account auf die Beta Seite zugreifen.

SSDS mit Proxy

Zuerst entscheidet man sich ob man lieber über die SOAP Schnittstelle oder über einen REST Ansatz arbeiten möchte. Der letztere ist recht flexibel einzusetzen, aber mir gefällt der vollständige SOAP Proxy besser. Insofern habe ich mich für die SOAP Schnittstelle entschieden. Nun habe ich mir aus der WSDL Beschreibung einen Proxy generieren lassen und kann auch schon loslegen. Wer mal einen Blick auf die WSDL werfen möchte, kann dies hier tun http://data.beta.mssds.com/soap/v1?wsdl

Des Weiteren werde ich komplett über SSL zugreifen, insofern habe ich das Binding auch auf Transport Sicherheit umgestellt und nutze entsprechend HTTPS.

Die Authority

Das erste was man benötigt ist das Einrichten der Authority. Die Authority ist Bestandteil der URI und wird auch später für die Verrechnung des Dienstes genutzt. Ich habe meine Authority einfach “running-man” genannt und die volle URI für den Dienst sieht für meine Authority nun folgendermaßen aus:

http://running-man.data.beta.mssds.com

Die Authority erstellt man allerdings programmatisch. Grundsätzlich muss man sich immer authentifizieren und insofern habe ich einen kleinen Helper in meiner Test-Anwendung der dem Proxy entsprechend Benutzernamen und Passwort setzt.

   1: private static void ProvideProxyCredentials( SitkaSoapServiceClient proxy )
   2: {
   3:     proxy.ClientCredentials.UserName.UserName = "benutzer";
   4:     proxy.ClientCredentials.UserName.Password = "passwort";
   5: }

Die Authority erstellt man mit folgendem Code:

   1: using( var proxy = new SitkaSoapServiceClient() )
   2: {
   3:     ProvideProxyCredentials( proxy );
   4:  
   5:     var serviceScope = new Scope();
   6:     var authority = new Authority
   7:     {
   8:         Id = "running-man"
   9:     };
  10:  
  11:     proxy.Create( serviceScope, authority );
  12: }

Hat man das ausgeführt, so kann man im Internet Explorer bereits auf die Authority zugreifen

shot1

Container und Entities

Nachdem der Grundstein gelegt ist lassen sich nun auch Container und Entititäten anlegen. Das ganze ist eine 3-Stufige Hierarchie. Eine Authority hat einen oder mehrere Container. Ein Container hat eine bis mehrere Entitäten. Oder wenn man es mit einem relationalen Store vergleicht: Authority == Datenbank, Container == Tabelle, Entity == Zeile. Der Vergleich hinkt natürlich, da Entitäten nicht die gleiche Struktur innerhalb eines Containers haben müssen und zudem auch noch die Entitäten Art unterschiedlich sein kann.

Für meinen Versuch habe ich einen Container angelegt der Trainings Daten beherbergen soll, insofern habe ich diesen einfach “training” genannt. Hier der Code:

   1: using( var proxy = new SitkaSoapServiceClient() )
   2: {
   3:     ProvideProxyCredentials( proxy );
   4:  
   5:     var scope = new Scope
   6:     {
   7:         AuthorityId = "running-man"
   8:     };
   9:  
  10:     var container = new Container
  11:     {
  12:         Id = "training"
  13:     };
  14:  
  15:     proxy.Create( scope, container );
  16:  
  17: }

Ist der Container erstellt kann man unmittelbar im Browser prüfen ob dieser auch angelegt worden ist

shot2

Nun gilt es die ersten Daten zu speichern. Hierfür beschreibt man eine Entität und speichert diese unter dem Scope ab. Der Scope für die Entität bildet sich aus der Authority und dem Container. Das Schlüsselmanagement für die Entitäten macht man selbst, für das Demo mache ich einfach fest kodierte Werte, eine einfache flexible Lösung wären zum Beispiel das Verwenden von Guids.

   1: using( var proxy = new SitkaSoapServiceClient() )
   2: {
   3:     ProvideProxyCredentials( proxy );
   4:  
   5:     var scope = new Scope
   6:     {
   7:         AuthorityId = "running-man",
   8:         ContainerId = "training"
   9:     };
  10:  
  11:     var entity = new Entity
  12:                      {
  13:                          Id = "2",
  14:                          Kind = "lga",
  15:                          Properties = new Dictionary<string, object>()
  16:                      };
  17:     entity.Properties[ "date" ] = DateTime.Now.ToShortDateString();
  18:     entity.Properties[ "time-must" ] = new TimeSpan( 1, 15, 0 ).ToString();
  19:     entity.Properties[ "time-is" ] = new TimeSpan( 1, 17, 22 ).ToString();
  20:     entity.Properties[ "pulse-max" ] = 145m;
  21:     entity.Properties[ "pulse-min" ] = 114m;
  22:     entity.Properties[ "pulse-average" ] = 129m;
  23:  
  24:     proxy.Create( scope, entity );
  25: }

Der Code legt die Entität an. Anmerken möchte ich zwei Dinge. Die Id in Zeile 13 ist der eindeutige Schlüssel der Entität in diesem Container. Diesen kann man auch entsprechend benutzen um auf die Entität zuzugreifen, auch über den Browser wie hier zu sehen.

shot3

Des Weiteren hat man in Zeile 14 die Art der Entität spezifiziert. Diese ist im Resultat anhand des Root-Elements des zurückgegebenen XML Dokuments zu sehen ==> lga. In einem Container lassen sich also mehrere Arten von Entitäten abspeichern.

Aktualisieren und Suchen von Daten

Es lassen sich natürlich auch die Daten manipulieren und suchen. Hat man den Schlüssel einer Entität so kann man natürlich direkt drauf zugreifen. Der folgende Code demonstiert wie man einen Wert in der Entität aktualisiert:

   1: using( var proxy = new SitkaSoapServiceClient() )
   2: {
   3:     ProvideProxyCredentials( proxy );
   4:  
   5:     var scope = new Scope
   6:     {
   7:         AuthorityId = "running-man",
   8:         ContainerId = "training",
   9:         EntityId = "2"
  10:     };
  11:  
  12:     var entity = proxy.Get( scope );
  13:  
  14:     entity.Properties[ "time-is" ] = new TimeSpan( 0, 59, 0 ).ToString();
  15:  
  16:     proxy.Update( scope, entity );
  17: }

Hat man aber nicht den Schlüssel oder man möchte eine komplette Liste von Entitäten bearbeiten oder anzeigen, so kann man entsprechend auch eine Abfrage absetzen. Das folgende Codebeispiel sucht nach allen Entitäten die vom Typ “lga” (Laufen Grundausdauer) sind:

   1: using( var proxy = new SitkaSoapServiceClient() )
   2: {
   3:     ProvideProxyCredentials( proxy );
   4:  
   5:     var scope = new Scope
   6:     {
   7:         AuthorityId = "running-man",
   8:         ContainerId = "training"
   9:     };
  10:  
  11:     var queryString = @"from e in entities where e.Kind == ""lga"" select e";
  12:     var entities = proxy.Query( scope, queryString );
  13:  
  14:     foreach( var entity in entities )
  15:     {
  16:         Console.WriteLine( "EntityId: {0}", entity.Id );
  17:         Console.WriteLine( "Time Must: {0}", entity.Properties[ "time-must" ] );
  18:         Console.WriteLine( "Time Is: {0}", entity.Properties[ "time-is" ] );
  19:     }
  20: }

Man kann auch über den Browser auf die Entitäten zugreifen, zum Beispiel alle Entitäten im Container “training” auflisten:

shot4

Daten im Web?

Klar, die Frage stellt sich ob man Daten im Web speichern möchte und was für einen Nutzen man dadurch erzielt. Primär macht es Sinn den Dienst dann zu nutzen wenn das Hosten einer eigenen Datenbank Lösung zu Kosten- oder Supportintensiv ist. Hier gilt es natürlich erst mal abzuwarten wie das eigentliche Abrechnungsmodell für die SQL Server Data Services aussehen wird. Dabei ist dieser Dienst nicht nur für Web-Anwendungen und –Dienste gedacht sondern kann natürlich auch von traditionellen Windows Anwendungen genutzt werden. So erspart man sich vielleicht das Ausrollen und Konfigurieren von lokalen SQL Server Express Instanzen, was mitunter auch nicht immer trivial ist.

Das wichtigste ist und bleibt sich Technologien anzuschauen, diese zu verstehen und dann auf Grundlage dessen einen sinnvollen Einsatz für diese zu bestimmen.