Geek. Coder. Gamer. Bayern Munich Fan.
Visit my blog stream http://writeline.io
My Name is Dariusz Parys
I'm also known as Writeline
I'm a Technical Evangelist @ Microsoft Germany and you can follow me on Twitter or visit my blog stream.
If so, check out this tool provided by Christian.
Vor einiger Zeit habe ich einen Workshop zum Thema SQL Server 2005 und CLR gehalten. Irgendwann kam das Thema auf wie man Typen als XML serialisiert am besten ablegen kann, so das die unterschiedlichen Versionen von einem Objekt auch von älteren Clients gelesen und modifiziert werden können ohne das Information neuerer Objekte verloren gehen. Die Datenintegrität kann man mittels zweier Attribute bei der Serialisierung gewährleisten: XmlAnyElementund XmlAnyAttribute. Eine Klasse Person hat folgende Eigenschaften
[ XmlType( "Person" ) ]
publicclass PersonV1
{
[ XmlElement( "Nachname" ) ]
public string Name;
[ XmlElement( "Email" ) ]
public string Email;
}
Dies ist die erste Version der Klasse Person die wir in den XML Datentypen von SQL Server 2005 abspeichern. Serialisiert man das ganze mittels dem XmlSerializer erhält man folgendes XML:
<?xmlversion="1.0"encoding="utf-8"?>
<Personxmlns:xsd="http://www.w3.org/2001/XMLSchema"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<Nachname>Parys</Nachname>
<Email>somewhere@microsoft.com</Email>
</Person>
Clients die mit dieser Version arbeiten speichern also Personen Typen mit diesem Inhalt ab. Im Laufe der vielen Projektjahre erweitert sich das Person Objekt um neue Eigenschaften und behält die alten. Neue Clients arbeiten mit der folgenden Version:
publicclass PersonV2
public string Lastname;
[ XmlElement( "Alter" ) ]
public int Age;
[ XmlAttribute( "LetzteAnmeldung" ) ]
public DateTime LastLogin;
welches das folgende XML Fragment erzeugt:
<Personxmlns:xsd="http://www.w3.org/2001/XMLSchema"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"LetzteAnmeldung="2004-12-20T10:31:26.8913751+01:00">
<Nachname>Prengel</Nachname>
<Alter>36</Alter>
Nehmen wir an das Nachname und Email die benötigten Felder sind um Personen zu erstellen und zu modifizieren und das alle zusätzlichen Eigenschaften optional sind. Mit dieser Annahme dürfen auch Clients die mit dem Version 1 Objekt arbeiten produktiv die Daten modifizieren. Das hat nun allerdings ein kleines Problem. Lädt ein Client der PersonV1 Objekte versteht einen Datensatz der mit einem PersonV2 Client erzeugt wurde gehen die Version 2 spezifischen Informationen verloren wenn dieser Datensatz durch den V1 Client aktualisiert wird. Die Information Alter und LetzteAnmeldung enden im Nirvana. Ist eigentlich auch Einleuchtend, denn der XmlSerializer hat keine Eigenschaften im Objekt PersonV1 gefunden in welche diese zusätzlichen Informationen deserialisiert werden können. Hier kommen nun die Attribute XmlAnyElementund XmlAnyAttributezum Einsatz. PersonV1 müsste so aussehen
[XmlAnyElement]
public XmlElement[] reservedElems;
[XmlAnyAttribute]
public XmlAttribute[] reservedAttrs;
damit dieser Information nicht verloren geht. Bearbeitet nun ein Client der Version 1 versteht ein Version 2 erzeugten Datensatz bleiben die Version 2 spezifischen Daten erhalten. Der Deserialisierungsmechanismus weisst einfach alle zusätzlichen unbekannten Elemente in das jeweilige XmlElementArray oder in das XmlAttributeArray. Damit bleiben diese Informationen auch erhalten und serialisieren sich auch wunderbar wieder. Ein kleines Rettungsboot für ungeladene Gäste.