Mittwoch, 21. August 2013

Generische Datenspeicherung mit XML - Teil 2 (Generic Entity Data Storage)

Bisherige Teile dieser Lecture

Falls Sie die bisherigen Teile dieser Lecture noch nicht kennen:

Kurze Rekapitulation was wir machen wollen

Wir wollen also Objekte in Form ihrer XML-Serialisierung als Strings in einem generischen Data Storage speichern. Dabei kann es sich z.B. um einen SQL Server, eine XML-Datei oder ähnliches handeln. Außerdem haben wir festgestellt, das jedes Objekt über eine eindeutige Objekt-ID identifizierbar sein muss. Fokussieren wir uns auf die rein technische Umsetzung dieser Anforderungen:

Implementierung der technisch notwendigen Elemente

Um der Forderung nach einer eindeutigen Objekt-ID gerecht zu werden, definieren wir zunächst ein Interface IGenericObject. Dieses muss von allen Objekten, welche in unserem Data Storage gespeichert werden können sollen, implementiert werden. Das Interface definiert dabei nur eine String-Property GenericObjectId

Hier ist jetzt allerdings noch ein kleiner Einschub notwendig: Um ein Objekt in unserem Data Storage wirklich eindeutig identifizieren können, reicht die Objekt-ID nicht aus. Wir müssen außerdem noch dessen Klasse kennen (genauer: deren FullClassName). Ein "User" mit der Id "A" ist eben etwas anderes als eine "Address" mit der Id "A". Außerdem wollen wir den gleichen Data Storage evtl. für verschiedene Applikationen benutzen - die vielleicht alle die gleiche User-Klasse verwenden. Aus diesem Grund führen wir noch einen "ApplicationKey" ein

Als erstes zentrales Element definieren wir dann die Klasse GenericEntity. Diese hat als Hauptaufgabe die Durchführung der XML-Serialisierung / XML-Deserialisierung. Sie hat einen Konstruktor, welchem wir das zu speichernde generiche Objekt übergeben können (beim Schreiben in den Data Storage) und eine Methode CreateGenericObject() welche das zu lesende generische Objekt zurück gibt (beim Lesen aus dem Data Storage). Ein Generic Entity ist also die speicherbare Repräsentation eines zu speicherndes Objektes!

Wenig überraschend ist dann noch das zweite zentrale Element - der eigentliche Data Storage, in welchem wir dann die Generic Entities speichern können (wichtig hier - in dem Data Storage werden nicht die Objekte, sondern, wie gesagt, die Generic Entities gespeichert). Mit den konkreten Implementierungen - z.B. ein Generic Entity Data Storage in Form eines SQL-Servers oder einer XML-Datei - beschäftigen wir uns in den folgenden Teilen dieser Lekture. Für den Anfang definieren wir erst einmal ein Interface IGenericEntityDataStorage. Hier legen wir Methoden fest um:

  • eine Generic Entity oder eine Liste von Generic Entities zu speichern
  • eine bestimmte Generic Entity oder eine Liste von Generic Entities zu finden
  • eine bestimmte Generic Entity oder eine Liste von Generic Entities zu löschen
  • zu ermitteln welche Klassenarten und Applikationen gespeichert sind (für administrative Zwecke)

Hier eine Übersicht zu den definieren Elementen:

Die Properties der Klasse GenericEntity sind alles bis auf die XmlSerialization Property vom Datentyp String. Die XmlSerialization Property ist vom Datentyp XElement. Die Umwandlung in einen String erfolgt dann erst innerhalb eines Data Storage (wenn nötig)

... und wie diese miteinander interagieren:

Über den Konstruktor der Klasse GenericEntity wird das zu speichernde "User"-Objekt in einen XML-String serialisiert und die Informationen zur Identifikation werden ermittelt. Das erzeugte Objekt wird im Data Storage gespeichert. Dort kann es wieder ausgelesen werden und über die Methode CreateGenericObject kann das ursprüngliche "User"-Objekt wieder hergestellt werden

Details zur XML-Serialisierung

Der Vollständigkeit halber hier ein Code-Ausschnitt zur XML-Serialisierung eines Objektes in einen String als Beispiel-Implementierung:

User myTestUser = new User();
StringWriter writer = new StringWriter();
XmlWriter xmlWriter = XmlWriter.Create(writer);
XmlSerializer serializer = new XmlSerializer(typeof(User));
serializer.Serialize(xmlWriter, myTestUser);
string xmlString = writer.ToString();

Sowie die Deserialisierung dieses XML-Strings zurück in eine Objekt-Instanz:

string xmlString = "<xml.....";
StringReader reader = new StringReader(xmlString);
XmlReader xmlReader = XmlReader.Create(reader);
XmlSerializer deserializer = new XmlSerializer(typeof(User));
User myDeserializedUser = deserializer.Deserialize(xmlReader) as User;

Anmerkung: der echte Code sieht natürlich etwas anders aus und es werden da dann auch using Directive verwendet!

Nächster Schritt

Nachdem wir nun in der Lage sind ein Objekt mittels XML-Serialisierung prinzipiell speichern zu können, wollen wir mit den konkreten Implementierungen von Generic Entity Data Storages beginnen. Im Einzelnen werden wir dabei in den nächsten Teilen dieser Lecture folgende generische Speicherarten implementieren:

  • In einer XML-Datei mit LINQ to XML
  • Im Arbeitsspeicher (Memory) - hier natürlich ohne Persistenz nach Applikations-Ende
  • In einer SQL Server Datenbank mit LINQ to SQL

... to be continued

Autor: Thomas Gysser | www.advadev.de

Keine Kommentare:

Kommentar veröffentlichen