Synchronisation von Trainingsdaten

Transcrição

Synchronisation von Trainingsdaten
Leopold-Franzens-Universität
Innsbruck
Institut für Informatik
Forschungsgruppe Quality Engineering
Synchronisation von Trainingsdaten
Bachelorarbeit
eingereicht bei Univ.-Prof. Dr. Ruth Breu
Andreas Grill
Thomas Juen
Innsbruck, 18. September 2009
Vorwort
1
Motivation
Unser Auftraggeber InfPro IT Solutions GmbH entwickelte vor einigen Jahren
zusammen mit der Firma SP Sportdiagnosegeräte GmbH ein System zur
sportartspezifischen Trainingsplanung und –steuerung. Diese Software findet ihren
Einsatz derzeit zum Großteil im Spitzensportbereich und erleichtert Coaches die
Planung, Analyse und vor allem Verteilung von Trainingsplänen an Athleten und
Athleten-Gruppen.
Die Version 4 des Trainingstimers (so lautet der Name des Produktes) persistiert die
Daten in allen Lizenzmodellen (Trainer, Athlet, …) in einer lokalen Microsoft
Access Datenbank und bietet über ein Synchronisationsmodul die Möglichkeit Daten
auszutauschen.
Derzeit entsteht aus diversen Gründen eine komplett überarbeitete und erweiterte
Version der Software, mit dem Namen Trainingstudio. Diese wird nicht mehr mit
einem einzigen Datenbanksystem auskommen, da neben der lokalen Datenhaltung
(hierfür wird das Datenbanksystem Microsoft SQL CE zum Einsatz kommen) auch
eine zentrale Online-Datenbank (Microsoft SQL Server) geplant ist.
Ziel unseres Projektes war es, ein Synchronisationskonzept auszuarbeiten, welches
unabhängig vom verwendeten Datenbanksystem eingesetzt werden kann. Darüber
hinaus zählte auch die Implementierung des Konzeptes in Form einer
Programmierschnittstelle (API) und die konfigurationslose Einbindung in das
Trainingstudio zu unseren Aufgaben.
2
Abstract
Several years ago InfPro IT Solutions GmbH developed a system for sport intrinsic
scheduling and controlling in collaboration with SP Sportdiagnosegeräte GmbH.
This software is mainly used in the domain of top-class sports and makes the
Vorwort
4
planning and analytic phases easier but primarily the distribution of plans to athletes
and groups of athletes.
Version 4 of this software called Trainingstimer stores the data of all possible
license-variants in a local Microsoft Access Database and uses a synchronization
module for providing the possibility of exchanging data.
For various reasons a complete revised and extended version of the software with the
new name Trainingstudio is currently under development. The new version uses a
more sophisticated system for data storage. In addition to a local database (this time
Microsoft SQL CE is used) a central database server (Microsoft SQL Server) is a
planned feature.
The aim of this project was to create a synchronization concept, which can be used
independently of the underlying database system. Beyond that, we also had to
implement the concept in terms of a programming interface (API) and integrate an
initial support in the Trainingstudio software.
3
Danksagung
Im Laufe der Projektarbeit standen uns viele helfende Hände mit Rat und Tat zur
Seite. Besonders bedanken möchten wir uns bei:
Dipl.-Ing. Hansjörg Haller für die technische Betreuung, die unzähligen
Beratungsstunden und die geduldige Art und Weise den Projektfortschritt
konstant aufrecht zu erhalten.
Prof. Dr. Ruth Breu für ihre Betreuung und Unterstützung.
Ing. Thomas Schliernzauer und Dr. Harald Pernitsch der Firma SP
Sportdiagnosegeräte GmbH für ihre Unterstützung.
Frau Jasmin Karner für den raschen Review der Dokumentation.
Unseren Familien und Freunden für ihre Hilfe und Unterstützung.
Inhaltsverzeichnis
Vorwort ................................................................................................................... 3
1
Motivation ............................................................................................ 3
2
Abstract................................................................................................. 3
3
Danksagung .......................................................................................... 4
Inhaltsverzeichnis .................................................................................................... 5
Einleitung ................................................................................................................ 9
4
Anforderungen ...................................................................................... 9
5
Technische Umgebung ....................................................................... 10
6
Umsetzung .......................................................................................... 11
7
Auswahl der Komponenten ................................................................ 12
8
7.1
Wahl des Betriebssystems ...................................................... 12
7.2
Wahl der Programmiersprache ............................................... 12
7.3
Wahl des Persistenz-Frameworks .......................................... 12
7.4
Wahl der Entwicklungsumgebung ......................................... 13
7.5
Wahl sonstiger Komponenten ................................................ 13
Ergebnis & Ausblick .......................................................................... 13
Pflichtenheft .......................................................................................................... 15
9
Aktuelle Situation ............................................................................... 15
10
EDV Technische Voraussetzungen .................................................... 15
11
Geschäftsprozessmodell ..................................................................... 16
12
Anwendungsfälle ................................................................................ 16
Inhaltsverzeichnis
6
Softwarearchitektur ............................................................................................... 19
13
Begriffserklärungen ............................................................................ 19
14
Softwareverteilung ............................................................................. 20
15
16
17
14.1
ThemiSync-Erweiterte IBOF-Applikation ............................. 20
14.2
Applikationsdatenbank ........................................................... 20
14.3
Transportdatenbank ................................................................ 20
14.4
Grafischer Überblick der Softwarekomponenten ................... 21
Technologiekonzept ........................................................................... 21
15.1
Systemaufbau ......................................................................... 22
15.2
Spezielle Technologien .......................................................... 24
15.3
Synchronisation ...................................................................... 27
Logische Sicht .................................................................................... 39
16.1
Komponentenarchitektur ........................................................ 39
16.2
Querschnittskomponente ........................................................ 47
16.3
Anwendungskern .................................................................... 48
Implementierungssicht ....................................................................... 54
17.1
Initialisierung ......................................................................... 54
17.2
Metadaten ............................................................................... 60
17.3
Konfiguration ......................................................................... 67
17.4
Synchronisation ...................................................................... 71
Qualitätssicherung ................................................................................................. 91
18
Analyse ............................................................................................... 92
19
Entwurf ............................................................................................... 92
20
Implementierung................................................................................. 93
20.1
Extreme Programming (XP) .................................................. 93
20.2
Codereviews ........................................................................... 94
Inhaltsverzeichnis
7
20.3
Pair-Programming .................................................................. 94
20.4
Unittests.................................................................................. 94
20.5
Cruisecontrol .......................................................................... 94
21
Integration........................................................................................... 95
22
Einsatz & Wartung ............................................................................. 95
Benutzerhandbuch ................................................................................................. 97
23
Einleitung ........................................................................................... 97
24
Beispielapplikation ............................................................................. 97
24.1
Einleitung ............................................................................... 97
24.2
Benötigte DLLs ...................................................................... 98
25
ThemiSync Konfigurationstool .......................................................... 99
26
Vorbereitungen (Datenbank, IBOF) ................................................. 100
27
26.1
Datenbank ............................................................................ 100
26.2
IBOF ..................................................................................... 103
Konfiguration (ThemiSync) ............................................................. 106
27.1
Exportkonfiguration (ExportConfigurationEntity) .............. 107
27.2
Importkonfiguration (ImportConfigurationEntity) .............. 108
27.3
Konfigurationsgruppe (ConfigurationGroupEntity) ............ 110
27.4
Konfigurationsgruppen-Zuordnung
(ConfigurationGroupMappingEntity) ............................................... 110
28
27.5
Entitätstyp (EntityTypeEntity) ............................................. 110
27.6
Beispielapplikation – ThemiSync Konfiguration................. 111
API-Schnittstellen............................................................................. 115
28.1
ThemiSyncBase .................................................................... 116
28.2
ThemiSyncConfig ................................................................ 117
28.3
ThemiSyncExport ................................................................ 117
Inhaltsverzeichnis
28.4
8
ThemiSyncImport ................................................................ 118
Abbildungsverzeichnis ........................................................................................ 121
Literaturverzeichnis............................................................................................. 123
Einleitung
4
Anforderungen
Die Firma InfPro IT Solutions GmbH entwickelt und vertreibt zusammen mit der
Firma SP Sportdiagnosegeräte GmbH den Trainingstimer - eine Software zur
Planung von sportartspezifischen Trainingseinheiten. In der aktuellen Version
besteht bereits die Möglichkeit Trainingspläne und sonstige Daten zwischen
Trainern und Athleten zu synchronisieren. Hier gibt es allerdings neben
Performanceproblemen
auch
diverse
andere
Gründe,
welche
ein
neues
Synchronisationskonzept erforderlich machen.
Im Zuge eines groß angelegten aktuellen Relaunchs der Software welche dann unter
dem Namen Traininstudio vermarktet wird, soll ein solches neues Konzept zum
Einsatz kommen. Das ist die Grundlage für die Entstehung dieses Projektes, welches
konkretisiert folgende Anforderungen stellt:
Synchronisationskonzept
Die grundsätzliche Anforderung besteht darin ein Konzept auszuarbeiten, welches
die Synchronisation zwischen beliebig vielen Trainingstudio-Instanzen ermöglicht.
Dabei ist es von großer Bedeutung, dass Konflikte verlässlich erkannt werden,
während konfliktfreie Datenänderungen ohne weiteres Zutun abgeglichen werden.
Weiters muss das Konzept in Form einer API implementiert werden und diese in
seiner Grundfunktionalität (ohne endgültige Konfiguration) in das Trainingstudio
integriert werden.
Flexible Konfiguration
Die Art beziehungsweise Struktur der synchronisationsrelevanten Daten ist zur Zeit
der Systementwicklung nicht bekannt und muss daher flexibel konfigurierbar sein.
Einleitung
10
Datenbanksystemunabhängigkeit
Die Daten des Trainingstudio werden derzeit für jede Instanz lokal in einer
Mircosoft SQL CE Datenbank persistiert. Da es aber Firmen-intern bereits
Überlegungen zu einer globalen Trainingsdatenbank für die gesamte TrainingstudioCommunity gibt muss davon ausgegangen werden, dass in naher Zukunft auch
zwischen verschiedenen Datenbanksystemen synchronisiert werden muss.
Synchronisationsdatenübertragung
Erfahrungswerte der Firma InfPro IT Solutions GmbH besagen, dass vor allem im
Spitzensportbereich oft an sehr exotischen Orten trainiert wird. Aus diesem Grund
darf
nicht
davon
ausgegangen
werden,
dass
für
die
Übertragung
der
Synchronisationsdaten Internet verwendet werden kann. Trotzdem muss diese
Möglichkeit im Konzept vorgesehen werden.
Rollenkonzept
Im Trainingstudio wird es grundsätzlich zwei Benutzergruppen geben – Trainer und
Athleten. Das Synchronisationssystem muss die Möglichkeit bieten, differenzierte
Synchronisationsabläufe
zu
konfigurieren
um
eine
Berechtigungshierarchie
umzusetzen. Damit sollen unter anderem per Konfiguration richtige, aber für die
Applikation irrelevante Synchronisationskonflikte automatisiert aufgelöst werden.
Datensicherheit
Bereits die aktuelle Version des Trainingstimers ist in verschiedenen Sportvereinen
verschiedener Länder im Einsatz. Die Trainingspläne der Vereine sind also zum Teil
sehr sensible Daten und dürfen unter keinen Umständen an ein unvorhergesehenes
Ziel
synchronisiert
werden.
Deshalb
muss
für
den
Transfer
der
Synchronisationsdaten ein Sicherheitskonzept eingesetzt werden.
5
Technische Umgebung
Um eine höchstmögliche Kompatibilität mit dem Trainingstudio in Version 1.0 der
Firma InfPro zu erzielen, orientierten wir uns an Technologien welche dort bereits
Verwendung gefunden haben. Dazu zählt die Programmiersprache C# 2.0 und das
Einleitung
11
Microsoft .Net Framework 2.0. Weiters verwendeten wir – gleich wie das
Trainingstudio
–
IBOF1
(Version
3.0)
als
Persistenz-Framework.
Als
Transfermedium verwendeten wir die Microsoft SQL CE Datenbank (Version 2.0),
welche über IBOF angesteuert werden kann.
6
Umsetzung
Kernstück der Umsetzung ist die Erweiterung der Software Trainingstudio. Dabei
gilt es eine Möglichkeit zu schaffen um diverse Daten, in erster Linie
Trainingspläne,
zwischen
beliebig
vielen
Trainingstudio-Softwareinstanzen
abzugleichen.
Einer der häufigsten Fälle der eine Synchronisation verlangt ist die Verteilung eines
Trainingsplans, der von einem Trainer für einen oder mehrere Athleten erstellt
wurde. Um ein, für den Trainer nützliches Feedback zum Trainingserfolg der
Athleten zu erhalten, wird im Normalfall der Athlet seine durchgeführten und zum
Teil veränderten Trainingsdaten zurücksynchronisieren. Zusätzlich soll auch ein
Austausch von diversen Übungs- beziehungsweise Trainingseinheiten-Vorlagen
unter
Trainern,
sowie
die
Verteilung
von
Terminen,
Perioden
und
Tagesinformationen möglich sein.
Bei der Umsetzung wurde gemäß der Anforderung darauf geachtet, dass der gesamte
Synchronisationsprozess
direkt,
lokalitätsunabhängig
und
ohne
weitere
Zwischenkomponenten (z.B. Synchronisationsserver) möglich ist. Ein OnlineDatenabgleich ist über eine Erweiterung (Serverinstanz) vorgesehen und somit leicht
realisierbar, jedoch ist aufgrund der teilweise exotischen Trainingslokalitäten der
Athleten eine Peer-To-Peer Synchronisation vorrangig und somit fixer Bestandteil
der Umsetzung.
InfPro baut einen Großteil seiner Projekte, darunter auch das Trainingstudio, auf
dem Firmeneigenen Persistenz-Framework IBOF auf. Aus diesem Grund war es
wünschenswert und eine zusätzliche Herausforderung ein Konzept zu erarbeiten,
1 IBOF = InfPro Business Object Framework (Eigenentwicklung der Fa. InfPro)
2 „ThemiSync“ ist die Bezeichnung der Synchronisations-API welche im Zuge des hier
Einleitung
12
welches keine direkte Abhängigkeit zum Produkt Trainingstudio hat, sondern
generisch für alle IBOF-basierenden Projekte als Erweiterung eingesetzt werden
kann. Da IBOF bereits sehr viele der benötigten Daten für eine generische
Umsetzung des Synchronisationskonzepts zur Verfügung stellt, bot sich eine solche
an und wurde zur Gänze realisiert.
7
Auswahl der Komponenten
Die Komponenten, welche bei der Realisierung des Projektes ThemiSync2 zum
Einsatz kamen waren zum Teil vom Auftraggeber vorgegeben oder wurden vom
Projektteam ausgewählt. Die Gründe für die Auswahl beziehungsweise Verwendung
der jeweiligen Komponenten seien im Folgenden genannt:
7.1
Wahl des Betriebssystems
Da die Firma InfPro IT Solutions einen Großteil Ihrer Produkte für Windows
basierende Betriebssysteme entwickelt (auch das Trainingstudio ist nur für
Windows-OSs geeignet) war die Entscheidung des Betriebssystems mehr oder
weniger bereits vorgegeben. Bei der Implementierung wurde Windows XP SP 3
verwendet.
7.2
Wahl der Programmiersprache
Die Software Trainingstudio - und auch ein Großteil der anderen Produkte der Firma
InfPro - wurde in der Programmiersprache C# implementiert. Um zum Einen
möglichst kompatibel zu bleiben und zum Anderen eine Firmeninterne
Weiterentwicklung von ThemiSync möglichst einfach zu halten, entschieden auch
wir uns für diese Programmiersprache. Es wurde Microsoft C# in der Version 2.0
verwendet.
2 „ThemiSync“ ist die Bezeichnung der Synchronisations-API welche im Zuge des hier
dokumentierten Projektes entstand. Es ist eine Zusammensetzung der Wörter „Themis“ (griech.
Göttin der Gerechtigkeit, Ordnung und Philosophie) und „Synchronisation“
Einleitung
7.3
13
Wahl des Persistenz-Frameworks
Als Persistenz-Framework wurde uns von InfPro das Firmeneigene Framework
IBOF zur Verfügung gestellt. Dieses eignete sich besonders gut, da es bereits sehr
viel Funktionalität bereitstellte und zusätzlich noch während der Entwicklungszeit
beliebig erweitert werden konnte und auch wurde.
7.4
Wahl der Entwicklungsumgebung
Microsoft bietet für die Programmierung im .Net Framework eine umfangreiche
Entwicklungsumgebung. Visual Studio wurde für die Implementierung von
ThemiSync in der Version v9 SP1 eingesetzt, da es die Standardsoftware ist und
bereits im Vorfeld gute Erfahrungen damit gemacht wurden.
7.5
Wahl sonstiger Komponenten
Für die Realisierung von diversen ThemiSync-Funktionalitäten wurden teilweise
Komponenten von Dritten verwendet. Dazu zählen Folgende:
SharpZipLib
SharpZipLib 0.8 ist eine Klassenbibliothek, welche diverse Funktionen für den
Umgang mit komprimierten Dateien bietet. Die Entscheidung fiel auf diese
Komponente, da sie sehr umfangreich ist und zudem der GNU General Public
License unterliegt.
NUnit
NUnit ist ein Framework für den Einsatz von Unittests bei der Softwareentwicklung.
Für ThemiSync wurde NUnit 2.4 verwendet, da es auch in der Firma InfPro
eingesetzt wird.
NVelocity
NVelocity ist ein Werkzeug um zur Laufzeit dynamisch auf Objekte zuzugreifen. Es
ist ein Port der Open Source Java Template Engine „Velocity”. Da keine alternative
Software mit der gewünschten Funktionalität gefunden wurde, war diese
Entscheidung klar.
Einleitung
8
14
Ergebnis & Ausblick
Zusammenfassend wurde ThemiSync zu einem Synchronisationswerkzeug, welches
sehr flexibel eingesetzt werden kann. Der generische Ansatz und die direkte
Integration in den IBOF-Generator ermöglichen eine sehr einfache Erweiterung aller
bestehenden beziehungsweise neuen IBOF-Softwareprojekte. Damit kann über
wenige Konfigurationsschritte die geforderte Synchronisation von TrainingstudioDaten umgesetzt werden und zusätzlich können die verschiedensten Szenarien, die
einen Datenabgleich zwischen zwei oder mehreren Datenbanken erfordern umgesetzt
werden.
ThemiSync ist bereits in das Trainingstudio integriert und wurde von der Firma
InfPro IT Solutions für den endgültigen Einsatz konfiguriert. Die API wird in Kürze
diversen Live-Tests unterzogen.
Das Resultat des Projektes ist sehr generisch einsetzbar und bietet viele
Schnittstellen für diverse Erweiterungen. Aus diesem Grund ist ThemiSync für
zukünftige Projekte der Firma InfPro IT Solutions eine solide Basis wenn es um die
Realisierung von Synchronisationsszenarien geht. Es bleibt zu hoffen, dass die API
für die Firma InfPro IT Solutions lange nützlich sein wird.
Pflichtenheft
9
Aktuelle Situation
Die Firma InfPro IT Solutions GmbH entwickelt zusammen mit der Firma SPSport
GmbH seit einigen Jahren eine Softwarelösung, welche als Planungs- und
Steuerinstrument für Trainingskonzepte im Spitzensport-Bereich dient.
Konkret ermöglicht diese Software, der Trainingstimer, Trainingspläne zu erstellen
und diese an Athleten-Gruppen zu verteilen.
Diese genannte Verteilung wird bereits bei der aktuellen Trainingstimer-Version
über Synchronisationsprozesse realisiert, weist allerdings einige Schwachpunkte auf.
Für die aktuell entstehende Relaunch-Version des Trainigstimers mit dem Namen
Trainingstudio soll auch eine Neuentwicklung dieses Synchronisationsprozesses
realisiert
werden,
was
die
Aufgabe
dieser
Projektarbeit
ist.
Die
neue
Synchronisationslösung soll im Gegensatz zur Aktuellen objektorientiert und
transaktionssicher sein.
10
EDV Technische Voraussetzungen
.Net 2.0 – Kompatibles Betriebssystem.
Entsprechende Umgebung, damit Trainingstudio lauffähig ist.
IBOF – Kompatibles Datenbanksystem für Quell- und Zieldatenbank.
IBOF – Kompatibles Datenbanksystem für Transport-Container3.
Übertragungsmedium für die Synchronisationsdaten (z.B.: USB-Stick,
Internet, …).
3 Medium um die Synchronisationsdaten von der Quell- zur Zieldatenbank zu übertragen.
Pflichtenheft
11
16
Geschäftsprozessmodell
In folgender Abbildung 1 wird ein Überblick über den Ablauf allgemeiner
Synchronisationsvorgänge mit ThemiSync dargestellt.
Applikation 1 (Quelle)
Synchronisation
Selektion der zu exportierenden Daten aus der Quellreplica
(Anhand von Meta- und Konfigurationsdaten)
Speichern dieser Daten im Transport-Container
Applikation 2 (Ziel)
Transport der Daten (Transport-Container)
Selektion der zu importierenden Daten aus dem Transport-Container
(Anhand von Konfigurationsdaten)
Speichern dieser Daten in der Zielreplica (Konfliktbehandlung)
Abbildung 1: Ablauf allgemeiner Synchronisationsvorgang
12
Anwendungsfälle
In der folgenden Abbildung 2 werden die Anwendungsfälle von ThemiSync
visualisiert:
Pflichtenheft
17
Konfigurieren
Exportieren
User
Importieren
Abbildung 2: Anwendungsfälle
Da ThemiSync eine vielseitig verwendbare Synchronisations-API ist, werden in der
Abbildung
2
die
Anwendungsfälle
nur
allgemein
visualisiert.
Diese
Anwendungsfälle können allerdings vielfältige Gestalt annehmen. Im Trainingstudio
beispielsweise kann ein Trainer mehrere Trainings-Pläne für seine Athleten
exportieren. Die Athleten können nun jeweils ihren persönlichen Plan importieren
und gegebenenfalls in abgeänderter Form erneut für den Trainer exportieren.
Softwarearchitektur
13
Begriffserklärungen
Zum besseren Verständnis seien vorab folgende Begriffe erläutert:
Replica
Der Begriff Replica bezeichnet einen Datenspeicher beliebiger Art, wobei es
sich im Rahmen von ThemiSync ausschließlich um ein IBOF-kompatibles
Datenbank Management System handelt.
Metadaten
Metadaten sind Zusatzinformationen zu Entitäten, die ThemiSync über
konkrete Datensätze mitverwaltet.
Hashcode
Ein Hashcode ist die Summe über bestimmte Attribute einer Entity. Er wird
nach einem bestimmten Algorithmus berechnet und ergibt bei identen
Attributwerten immer das gleiche Ergebnis. Ein Hashcode ermöglicht ein
effizientes
Vergleichen
von
analogen
Datensätzen
der
Quell-
beziehungsweise Zieldatenbank.
Entität
Eine
Entität
ist
eine
persistierte
Objektinstanz,
welche
je
nach
Geschäftsmodell-Hierarchie aus einem oder mehreren Datensätzen bestehen
kann.
Transport-Container
Als „Transport-Container“ wird das resultierende Medium eines ThemiSync
Exports bezeichnet. Dieser Container enthält alle für den Import bestimmten
Synchronisationsdaten, welche nach Synchronisationsgruppen (siehe 16.1.2)
aufgeteilt sind.
C# Reflection
Reflection ist eine Technologie, welche neben diversen anderen
Programmiersprachen von allen im .Net-Framework einsetzbaren Sprachen –
Softwarearchitektur
20
darunter auch C# - angeboten wird. Sie ermöglicht es, zur Laufzeit auf
diverse Informationen zu Klassen beziehungsweise deren Instanzen
zuzugreifen. Mit dem Einsatz von Reflection wird eine sehr hohe
Laufzeitflexibilität erreicht, allerdings müssen dafür Einbußen bei der
Ausführungsgeschwindigkeit in Kauf genommen werden.
14
14.1
Softwareverteilung
ThemiSync-Erweiterte IBOF-Applikation
Die ThemiSync API vereint sowohl Export- als auch Import-Funktionalität in einem
Softwarepaket und kann sämtliche IBOF Projekte um die Synchronisationsfähigkeit
erweitern. Für den sinnvollen Einsatz benötigt es mindesten zwei Softwareinstanzen,
welche auf denselben oder kompatiblen Datenbankmodellen aufbauen.
14.2
Applikationsdatenbank
Hierfür können alle IBOF-kompatiblen Datenbanksysteme zum Einsatz kommen. In
dieser Datenbank werden sowohl applikationsspezifische Daten gespeichert, als auch
von ThemiSync generierte und benötigte Metadaten persistiert.
14.3
Transportdatenbank
Standardmäßig wird für den Transfer der Synchronisationsdaten das filebasierte
Datenbanksystem Microsoft SQL Server Compact verwendet, allerdings ermöglicht
ThemiSync durch vordefinierte Schnittstellen beliebige andere IBOF-kompatible
Transportmedien einzusetzen.
Softwarearchitektur
14.4
21
Grafischer Überblick der Softwarekomponenten
Folgende Abbildung 3 stellt die Abhängigkeit der Softwarekomponenten grafisch
dar:
ApplikationsDatenbank
ThemiSync
Instanz
Transport
Datenbank
Abbildung 3: Softwareverteilung
15
Technologiekonzept
In diesem Abschnitt gehen wir im Detail auf die einzelnen Komponenten und die
verwendeten Technologien ein. Weiters wird hier ein Überblick über spezifischere
Synchronisierungsabläufe gegeben, welche anhand von Beispielen verdeutlicht
werden.
Softwarearchitektur
15.1
22
Systemaufbau
IBOF
ApplikationsInstanz
ApplikationsInstanz
ThemiSync
Export Modul
ThemiSync
Import Modul
DBMS
IBOF
DBMS
Exportvorgang
Importvorgang
Transfermedium
TransportContainer
DB
DB
...
DB
Abbildung 4: Systemaufbau
Im folgenden Abschnitt erhalten wird ein Überblick über die wichtigsten
Komponenten eines Systems, welches ThemiSync zur Datensynchronisation
verwendet gegeben. Abbildung 4 illustriert einen grafischen Überblick über den
Aufbau eines solchen Systems.
15.1.1
Applikationsinstanz
Die Applikationsinstanzen sind Softwarelösungen, welche auf unterschiedlichen
physikalischen Rechnern laufen können und in den synchronisierbaren Bereichen
kompatible Datenbankstrukturen besitzen. Dabei ist die Anzahl der Instanzen
theoretisch beliebig. Die Persistenzschicht einer jeden Applikationsinstanz muss auf
IBOF aufbauen, welches ab der Version 3.0.0.124 ThemiSync vollständig
unterstützt.
Softwarearchitektur
23
In den Applikationsinstanzen werden die Synchronisierungsprozesse angestoßen und
Synchronisationskonflikte beziehungsweise Spezialbehandlungen verarbeitet.
15.1.2
ThemiSync Export Modul
Das ThemiSync Export Modul ist ein fixer Bestandteil der Synchronisations-API
und wird von der Applikationsinstanz angesteuert. Aufgabe dieses Moduls ist die
Analyse der für die Synchronisierung relevanten Daten mit Hilfe spezieller
Metadaten.
Weiters erstellt das Export Modul für jeden atomaren Synchronisierungsvorgang
eine Datei-basierte Datenbank, welche mit den Synchronisationsdaten befüllt wird.
Eine beliebige Anzahl dieser Datei-basierten Datenbanken wird zu einem
Transportcontainer zusammengefasst, was auch zu den Aufgaben des Export-Moduls
zählt.
15.1.3
Transfermedium
Für den Transport der Synchronisationsdaten kann ein beliebiges Medium verwendet
werden. Als Beispiele seien erwähnt: USB-Stick, Email-Versand, oder Übertragung
mittels WCF4.
15.1.4
ThemiSync Import Modul
Das Import Modul als fixer Bestandteil von ThemiSync nimmt einen
Exportcontainer
entgegen
und
verarbeitet
die
enthaltenen
Daten.
Die
Synchronisationsdaten im Exportcontainer werden mit dem Datenbestand der
Zieldatenbank verglichen und dabei nötige Synchronisationsprozesse ausgelöst. An
dieser Stelle können Synchronisationskonflikte auftreten, welche über registrierte
Methoden aus der importierenden Applikationsinstanz entsprechend behandelt
werden müssen.
4 Windows Communication Foundation
Softwarearchitektur
15.2
15.2.1
24
Spezielle Technologien
IBOF
Das „InfPro Business Object Framework“ deckt mit seiner Funktionalität das
gesamte
Spektrum
der
von
uns
benötigten
Interaktionen
mit
den
Datenbankmanagement-Systemen ab.
Ein wichtiger Bestandteil dieses Frameworks ist der IBOF Generator welcher unter
anderem die Möglichkeit bietet, aus einem Datenbankmodell CRUD5-fähigen Code
zu erstellen. Im Zuge dessen werden Zusatzinformationen zu jeder Klasse
mitgeliefert, welche in ThemiSync Verwendung finden. Damit ist eine Verwendung
von ThemiSync für eine nicht IBOF-kompatible Applikation nicht vorgesehen.
Weiters wurde IBOF auch für ThemiSync-interne Abläufe verwendet, womit das
Resultat
einen
höchstmöglichen
Kompatibilitätsgrad
mit
IBOF-basierenden
Applikationen erreicht.
Folgende Tabelle beschreibt die generierten Klassen-Typen und deren Funktionalität.
Klassentyp
Merkmal
Beschreibung
DAC-Klassen
-
Im Ordner „DAC“
Die
-
…DAC.cs
Classes“
generierten
dienen
„Data
Access
als
Mittler
zwischen Datenbank und IBOFbasierter Applikation. Für jeden im
IBOF-Generator konfigurierten Typ
mit dem aktiven Flag „Persist in
DB“ wir eine DAC-Klasse generiert
welche für alle Felder bereits eine
FindBy-Methode bereitstellt und
beliebig erweitert werden kann.
5 CRUD (Create-, Read-, Update-, Delete-Operationen) CRUD beschreibt die Grundfunktionalität der
Persistenzschicht.
Softwarearchitektur
Entity-Klassen
25
-
Im Ordner „Entities“
Für jeden konfigurierten Typ wird
-
…Entity.cs
eine Entity-Klasse generiert. Diese
stellen die eigentlichen Klassen des
Geschäftsmodells
dar.
Instanzen
davon können bei entsprechender
Konfiguration
direkt
persistiert
werden.
Info-Klassen
-
Im Ordner „Info“
Die
-
…EntityInfo.cs
enthalten in Form von Konstanten
statischen
Info-Klassen
Informationen über Klassenname
(Tabellenname)
und
Property-
Bezeichnungen (Felder) der EntityKlassen. Damit lassen sich bequem
DB-System
unabhängige
SQL-
Queries erstellen.
Test-Klassen
-
Im Ordner „UnitTests“
Für die automatisierte Überprüfung
-
…Test.cs
der Grundfunktionalität der EntityKlassen,
welche
per
Überschreibung diverser Methoden
beeinflusst werden kann, werden
vom IBOF Generator automatisch
UnitTest-Klassen erstellt.
15.2.2
NVelocity
NVelocity (Version 1.6) ist ein Port der Open Source Java Template Engine
„Velocity” (entwickelt von der Apache Software Foundation) nach C# .Net. Diese
Template Engine bietet sowohl lesenden und schreibenden Zugriff auf definierte
Instanzattribute, als auch einfache Kontrollstrukturen über eine simple Skriptsprache.
ThemiSync bedient sich dieser Library um die Konfiguration für den Entwickler
über Vorlagen (Templates) möglichst einfach zu halten. Diese Vereinfachung kommt
vor allem bei der Steuerung des Rollenkonzeptes zum Einsatz, ist aber so generisch
Softwarearchitektur
26
gehalten, dass dem Entwickler auch benutzerdefinierte Abfragen zur Verfügung
stehen. Die entsprechenden Attribute können direkt über die ThemiSync API
registriert werden. Abbildung 5 illustriert die Zugriffsmöglichkeiten auf einen
VelocityManager.
ThemiSyncBase
+GlobalVelocityManager : VelocityManager
+<<get>> GetConfigurationGroupVelocityManager(in configurationGroup : ConfigurationGroupEntity) : VelocityManager
1
1
Global
1
ConfigurationGroup
VelocityManager
*
ThemiSyncExport
ThemiSyncImport
Abbildung 5: VelocityManager Zugriffsmöglichkeiten
15.2.3
SharpZipLib
SharpZipLib ist eine Open Source Klassenbibliothek, welche den Umgang mit
Dateiarchiven im Vergleich zur nativen .Net-Implementierung erheblich vereinfacht
und erweitert. ThemiSync verwendet SharpZipLib zum Erstellen beziehungsweise
Einlesen
des
Transportcontainers,
welcher
eine
beliebige
Anzahl
von
Exportdatenbanken enthält. Eine Exportdatenbank enthält die Daten eines in sich
abgeschlossenen Exportvorgangs.
15.2.4
NUnit
NUnit ist ein Port von JUnit, ein Werkzeug zur Handhabung von Unit-Tests.
Softwarearchitektur
15.2.5
27
ILMerge
ILMerge ist ein Tool von Microsoft, welches das Zusammenfassen von mehreren
Assemblies zu einem Paket ermöglicht. Wir verwenden dies um die gesamte
Funktionalität von ThemiSync in einer einzigen DLL bereitstellen zu können.
15.3
Synchronisation
In diesem Abschnitt wird das Herzstück von ThemiSync – das konkrete
Synchronisationskonzept – im Detail beschrieben.
15.3.1
Synchronisations-Algorithmus
Für dieses Projekt galt es ein Synchronisationskonzept zu erarbeiten, um Daten
zwischen beliebig vielen Replicas automatisiert abzugleichen. Dabei kann nicht
davon ausgegangen werden, dass die Replicas sich untereinander zur Gänze
vertrauen können. Dadurch muss es eine Möglichkeit geben Synchronisationsdaten
auf Entitätsebene zu filtern um nur erlaubte Daten für die Synchronisation
freizugeben.
Für ThemiSync wurde ein Algorithmus verwendet, welcher folgende Eigenschaften
voraussetzt:
Jede synchronisierbare Entität besitzt in den Metadaten sowohl einen Hash des
aktuellen Objektstatus (CurrentHash6), einen sogenannten LastSyncHash7, welcher
den Objektstatus nach der letzten Synchronisation repräsentiert und ein Flag8
LocallyChanged9, welches angibt ob Änderungen vorliegen die noch nicht exportiert
wurden. Falls die Entität noch nie synchronisiert wurde, dann besitzt das Datenfeld
LastSyncHash keinen Wert.
6 CurrentHash wird in den Grafiken mit CH abgekürzt.
7 LastSyncHash wird in den Grafiken mit LSH abgekürzt.
8 Variable mit zwei möglichen Werten (True beziehungsweise False).
9 LocallyChanged wird in den Grafiken mit LC abgekürzt
Softwarearchitektur
Diese
drei
Datenfelder
28
genügen
bereits
für
diesen
Algorithmus
um
Synchronisierungskonflikte zu erkennen und gegebenenfalls automatisiert zu
beheben. Die Arbeitsweise des Algorithmus sieht wie folgt aus:
Wenn eine Entität geändert wird und das Flag LocallyChanged den Wert False
besitzt, dann wird der LastSyncHash mit dem alten Wert des Datenfeldes
CurrentHash
überschrieben
und
LocallyChanged
auf
True
gesetzt.
Ist
LocallyChanged bereits auf True, so wird der LastSyncHash auf seinem Wert
belassen. Das bedeutet, dass der LastSyncHash nur bei der ersten lokalen Änderung
nach jedem Exportvorgang vom originalen CurrentHash überschrieben wird. Damit
kann beim Importvorgang eindeutig entschieden werden, ob der Objektstatus auf
beiden Seiten verändert wurde, oder nur in der Quell-Replica. Das Flag
LocallyChanged trägt also entscheidend zur Minimierung von Konflikten bei.
Um die Arbeitsweise zu verdeutlichen wird diese anhand von Pseudo-Code im
folgenden Abschnitt nochmals beschrieben:
PROCEDURE OnEntityChanged
ARGUMENTS entity : the entity object which was changed.
BEGIN
IF entity.LocallyChanged = False THEN
entity.LastSyncHash := entity.CurrentHash
entity.LocallyChanged := True
ENDIF
entity.CurrentHash := the new hashcode of the entity.
END
Export:
Beim Exportieren wird für jede Entität der Synchronisationsdatenmenge eine Kopie
in den Transport-Container erstellt, und anschließend das Flag LocallyChanged in
der Quell-Replica auf False gesetzt.
Import:
Für jede Entität im Transport-Container wird überprüft, ob diese bereits in der ZielReplica existiert. Falls die Entität neu ist, wird sie eingefügt, andernfalls wird sie bei
Gleichheit des CurrentHashs ignoriert.
Softwarearchitektur
29
Unterscheiden sich allerdings die Hashcodes wird überprüft, ob der LastSyncHash
der Entität in dem Transport-Container mit dem CurrentHash der analogen Entität in
der Ziel-Replica übereinstimmt. Wenn dies der Fall ist, werden die Änderungen der
Entität in die Ziel-Replica übernommen. Ansonsten wurde ein Konflikt entdeckt und
die Konfliktbehandlung wird angestoßen. Wenn eine Entität importiert wird, so wird
dessen Flag LocallyChanged in der Ziel-Replica auf False gesetzt.
Um die Arbeitsweise des Algorithmus beim Importieren zu verdeutlichen wird diese
im Folgenden mittels Pseudo-Code erneut beschrieben:
PROCEDURE Import
ARGUMENTS entityLst : A list of entities that are in the export
container (source database) and might get imported.
BEGIN
doImport := False
FOR entity
entityLst
IF entity exists in the destination database
READ old entity from the destination database AS oldEntity
IF entity.CurrentHash
oldEntity.CurrentHash THEN
IF entity.LastSyncHash = oldEntity.CurrentHASH THEN
doImport := True
ELSE
READ from user defined conflict handling AS doImport
ENDIF
ENDIF
ELSE
doImport := True
ENDIF
IF doImport = True THEN
IMPORT entity to the destination database
entity.LocallyChanged := False
ENDIF
ENDFOR
END
Folgende Beispiele in Abbildung 6 bis Abbildung 9 veranschaulichen den
Synchronisationsalgorithmus grafisch in verschiedenen Szenarien:
Softwarearchitektur
30
Einfaches Synchronisations-Beispiel - Variante 1
Replica 1
Transport-Container
Replica 2
Neue Entität A wird gespeichert
A:ChangeTrackingEntity
CH=1, LSH=null, LC=T
A wird exportiert
A:ChangeTrackingEntity
A:ChangeTrackingEntity
CH=1, LSH=null, LC=F
CH=1, LSH=null
Replica 2 ist leer.
A wird importiert
A:ChangeTrackingEntity
CH=1, LSH=null, LC=F
A wird geändert
A:ChangeTrackingEntity
CH=2, LSH=1, LC=T
A wird exportiert
A:ChangeTrackingEntity
A:ChangeTrackingEntity
CH=2, LSH=1
CH=2, LSH=1, LC=F
A wird importiert
A:ChangeTrackingEntity
CH=2, LSH=1, LC=F
Abbildung 6: Einfaches Synchronisations-Beispiel Variante 1
Softwarearchitektur
31
Das Beispiel aus Abbildung 6 beschreibt einen einfachen Synchronisationsablauf mit
zwei Replicas.
Zu Beginn wird in der Replica 1 eine neue Entity (A) erstellt. Dabei wird der
CurrentHash über die Attributwerte berechnet und der LastSyncHash mit NULL
initialisiert. Nach dem Exportvorgang von Replica 1 wird das Flag LocallyChanged
auf False gesetzt um festzuhalten, dass diese Entität in ihrem aktuellen Zustand
exportiert wurde.
Auf Seite der Replica 2 wird während des Importvorganges festgestellt, dass keine
analoge Entität existiert. Sie wird neu erstellt und das Flag LocallyChanged auf False
gesetzt.
Die Änderung der Entität in Replica 2 bewirkt die Übernahme des LastSyncHash
vom
ursprünglichen
CurrentHash.
Dadurch
kann
beim
nächsten
Synchronisationsschritt (Replica 2 -> Replica 1) Konfliktlos entschieden werden,
dass die Entität nur in Replica 2 geändert wurde und somit in Replica 1
überschrieben werden kann.
Softwarearchitektur
32
Einfaches Synchronisations-Beispiel - Variante 2
Replica 1
Transport-Container
Replica 2
Neue Entität A wird gespeichert
A:ChangeTrackingEntity
CH=1, LSH=null, LC=T
A wird exportiert
A:ChangeTrackingEntity
A:ChangeTrackingEntity
CH=1, LSH=null, LC=F
CH=1, LSH=null
Replica 2 ist leer.
A wird geändert
A wird importiert
A:ChangeTrackingEntity
A:ChangeTrackingEntity
CH=2, LSH=1, LC=T
CH=1, LSH=null, LC=F
A wird geändert
A:ChangeTrackingEntity
CH=3, LSH=1, LC=T
A wird exportiert
A:ChangeTrackingEntity
A:ChangeTrackingEntity
CH=3, LSH=1, LC=F
CH=3, LSH=1
A wird importiert
A:ChangeTrackingEntity
CH=3, LSH=1, LC=F
Abbildung 7: Einfaches Synchronisations-Beispiel Variante 2
Softwarearchitektur
33
Das Beispiel in Abbildung 7 demonstriert eine mehrfache Synchronisation von einer
Replica (hier Replica 1) ausgehend. Dieses Szenario ist im Bezug auf das
Trainingstudio sehr interessant, da es in der Praxis häufig auftritt (Trainer ->
Athleten).
Wie auch im vorhergehenden Beispiel wird zu Beginn eine Entität (A) in Replica 1
erstellt. Beim Import in die Replica 2 wird wiederum festgestellt, dass keine analoge
Entität existiert (-> Entität wird erstellt).
Beim ersten Änderungsvorgang wird der LastSyncHash aktualisiert und das Flag
LocallyChanged auf True gesetzt. Bei der nächsten Änderung bleibt der
LastSyncHash aufgrund des LocallyChanged-Flags unverändert.
Mit diesen Informationen kann beim weiteren Synchronisationsschritt (Replica 1 ->
Replica 2) wieder ohne Konflikt importiert werden.
Softwarearchitektur
34
Synchronisations-Beispiel mit Konflikten
Replica 1
Transport-Container
Replica 2
A:ChangeTrackingEntity
A:ChangeTrackingEntity
CH=2, LSH=1, LC=F
CH=2, LSH=1, LC=F
A wird geändert
A wird geändert
A:ChangeTrackingEntity
A:ChangeTrackingEntity
CH=3, LSH=2, LC=T
CH=4, LSH=2, LC=T
A wird exportiert
A:ChangeTrackingEntity
A:ChangeTrackingEntity
CH=3, LSH=2, LC=F
CH=3, LSH=2
A wird importiert
Konfliktbehandlung:
Replica 2 gewinnt
A:ChangeTrackingEntity
CH=4, LSH=2, LC=T
A wird exportiert
A:ChangeTrackingEntity
A:ChangeTrackingEntity
CH=4, LSH=2
CH=4, LSH=2, LC=F
A wird importiert
Konfliktbehandlung:
Replica 1 gewinnt
A:ChangeTrackingEntity
CH=3, LSH=2, LC=F
Abbildung 8: Synchronisations-Beispiel mit Konflikten
Softwarearchitektur
Abbildung
8
35
zeigt
ein
klassisches
Konflikt-Szenario,
welches
eine
applikationsgesteuerte Konfliktbehandlung erfordert.
In der Ausgangssituation existiert in beiden Replicas eine synchrone Entität, welche
unabhängig verändert wird.
Replica 1 möchte nun ihre Änderungen in Replica 2 importieren. Da allerdings der
LastSyncHash der exportierten Entität nicht mit dem CurrentHash der Entität in
Replica 2 übereinstimmt, entsteht ein Konflikt, welcher auf Applikationsebene
aufgelöst werden muss. In diesem Beispiel wird davon ausgegangen, dass die
Konfliktbehandlung zu Gunsten von Replica 2 entschieden hat. Dadurch bleibt die
Entität in Replica 2 in ihrem Zustand unverändert.
In dem darauf folgenden Synchronisationsschritt wird nun versucht die Entität aus
Replica 2 mit der analogen Entität aus Replica 1 zu synchronisieren. Beim
Importvorgang wird aufgrund der Unterschiede zwischen den Werten des
LastSyncHash der exportierten Entität und dem CurrentHash der Entität in der ZielReplica erneut ein Konflikt erkannt.
Softwarearchitektur
36
Synchronisations-Beispiel mit mehreren Teilnehmern
Replica 1
Transport-Container
Replica 2
Transport-Container
Replica 3
A:ChangeTrackingEntity
CH=1, LSH=null, LC=T
A wird exportiert
A:ChangeTrackingEntity
A:ChangeTrackingEntity
CH=1, LSH=null, LC=F
CH=1, LSH=null
A wird geändert
A:ChangeTrackingEntity
A wird importiert
A wird importiert
Replica 2 ist leer.
CH=2, LSH=1, LC=T
Replica 3 ist leer.
A wird exportiert
A:ChangeTrackingEntity
A:ChangeTrackingEntity
CH=2, LSH=1, LC=F
CH=2, LSH=1
A:ChangeTrackingEntity
A:ChangeTrackingEntity
CH=1, LSH=null, LC=F
CH=1, LSH=null, LC=F
A wird importiert
A:ChangeTrackingEntity
CH=2, LSH=1, LC=F
A wird exportiert
A:ChangeTrackingEntity
A:ChangeTrackingEntity
CH=2, LSH=1, LC=F
CH=2, LSH=1
A wird importiert
A:ChangeTrackingEntity
CH=2, LSH=1, LC=F
A wird exportiert
A:ChangeTrackingEntity
A:ChangeTrackingEntity
CH=2, LSH=1
CH=2, LSH=1, LC=F
A wird importiert
A:ChangeTrackingEntity
CH=2, LSH=1, LC=F
Abbildung 9: Synchronisations-Beispiel mit mehreren Teilnehmern
Softwarearchitektur
37
In Abbildung 9 wird ein komplexeres Synchronisations-Szenario mit drei Replicas
dargestellt. Zu Beginn besitzt nur Replica 1 eine Entität, welche beim ersten
Synchronisationsvorgang mit den beiden anderen Replicas abgeglichen wird.
Im weiteren Verlauf erkennt man, dass der Algorithmus auch mit mehreren Parteien
nach selben Schema durchgeführt werden kann.
15.3.2
Importreihenfolge
Der folgende Algorithmus
dient zum
Berechnen
einer Reihenfolge der
unterschiedlichen Entitäts-Typen, welche ein problemloses Importieren ermöglichen
soll. Da Entitäts-Typen Abhängigkeiten auf andere Entitäts-Typen besitzen können,
sollte beim Importieren eine Reihenfolge angestrebt werden, sodass alle benötigten
Entitäten bereits vorhanden sind. Es gibt dabei drei unterschiedliche Variationen.
1. Ein nicht hierarchischer Verweis auf einen anderen Entitäts-Typ.
2. Ein hierarchischer Verweis auf den Eltern Entitäts-Typ10.
3. Ein nicht hierarchischer rekursiver Verweis auf denselben Entitäts-Typ.
Für die Variationen 1 und 2 existiert eine Reihenfolge – sofern keine Vererbungsoder Assoziationszyklen vorhanden sind – mit welcher die Entitäten problemlos
importiert werden können. Da das Importieren einer Entität von IBOF durchgeführt
wird, muss das Importieren einer hierarchischen Entität nur auf den wahren
beziehungsweise höchst spezialisierten Typ angewandt werden. Deshalb sollten
zuerst die in der Vererbungshierarchie höchst spezialisierten Typen importiert
werden, da ansonsten eine Entität mehrfach importiert wird.
Die Arbeitsweise des Algorithmus sieht folgendermaßen aus:
1. Zuerst
werden
alle
Entitäts-Typen
anhand
ihrer
Position
in
der
Vererbungshierarchie gruppiert, sodass die Entitäten in den unterschiedlichen
Gruppen keine hierarchischen Abhängigkeiten mit Entitäten in anderen
Gruppen besitzen.
10 IBOF ermöglicht ein objektorientiertes Vererbungskonzept ohne Mehrfachvererbung, wodurch nur
ein Eltern-Knoten zu einem Kind-Knoten existiert.
Softwarearchitektur
38
2. Nun wird eine beliebige Gruppe gewählt und alle Entitäts-Typen
durchlaufen. Die Reihenfolge der Entitäts-Typen sollte dabei vom
hierarchischen Spezialisierungsgrad absteigend geordnet sein. Dadurch sind
die Entitäts-Typen, die zur selben Gruppe gehören, untereinander bereits
richtig geordnet.
3. Falls der Entitäts-Typ bereits behandelt wurde wird er nun ignoriert um
endlose rekursive Aufrufe zu vermeiden.
4. Falls der Entitäts-Typ Verweise auf Entitäts-Typen außerhalb der Gruppe
besitzt (Forward-Links), dann werden die Sortiermaßnahmen (ab Schritt 2)
rekursiv auf die Hierarchie-Gruppen der referenzierten Typen angewandt.
Der aktuelle Entitäts-Typ wird nach den Entitäts-Typen eingereiht, die
rekursiv behandelt wurden.
5. Falls andere Entitäts-Typen Verweise auf den aktuellen Entitäts-Typ besitzen
(Backward-Links), dann werden die Sortiermaßnahmen (ab Schritt 2)
rekursiv auf diese Entitäts-Typen angewandt. Der aktuelle Entitäts-Typ wird
vor den Entitäts-Typen eingereiht, die rekursiv behandelt wurden.
6. Wenn alle Entitäts-Typen der Gruppe behandelt wurden, dann liegen die
Hierarchie-Gruppen,
die
mit
der
gewählten
Hierarchie-Gruppe
zusammenhängen, in einer absoluten Ordnung vor. Falls noch HierarchieGruppen existieren, welche mit den bereits behandelten Gruppen strukturell
nicht zusammenhängend sind, dann wird der Schritt 2 solange mit den neuen
Gruppen wiederholt, bis alle Gruppen behandelt wurden und eine Ordnung
für alle Gruppen existiert.
Folgender Pseudo-Code zeigt eine Beispielimplementierung für den beschriebenen
Algorithmus.
PROCEDURE Main
ARGUMENTS groupLst : A list of grouped entity types
BEGIN
FOR group
groupLst
CALL OrderGroups(group)
ENDFOR
END
PROCEDURE OrderGroups
ARGUMENTS group : A group of entity types in the same hierarchy
Softwarearchitektur
39
BEGIN
IF group is not marked THEN
MARK group
FOR forwardLink
group.forwardLinkLst
CALL OrderGroups(forwardLink)
ENDFOR
FOR entityType
group
ordered by specialization level descending
INSERT entityType at the end of orderedGroupsLst
ENDFOR
FOR backwardLink
group.backwardLinkLst
CALL OrderGroups(backwardLink)
ENDFOR
ENDIF
END
Die Prozedur Main bekommt bereits die Liste von gruppierten Entitäts-Typen
(groupLst) übergeben. Die einzelnen Gruppen dieser Liste können markiert werden,
sodass überprüft werden kann, ob die Gruppen bereits behandelt wurden. Dies
geschieht mit dem Befehl MARK. In die Liste orderedGroupsLst werden die
Entitäts-Typen geordnet eingefügt. Die Liste ist dabei global zugänglich, damit alle
rekursiven Methoden-Aufrufe auf die Liste zugreifen können.
Falls die Entitäts-Typen Zyklen oder Abhängigkeiten mit Variation 3 enthalten, so
kann der Algorithmus keine problemfreie Ordnung finden. Da der Algorithmus die
bereits behandelten Entitäts-Typen nicht mehr weiterverfolgt terminiert der
Algorithmus. Um die Entitäten später auch unter diesen Bedingungen zu
importieren, müssen vor dem Import-Vorgang die Entitäten manipuliert werden
(siehe 17.4.4).
16
16.1
Logische Sicht
Komponentenarchitektur
ThemiSync wird in vier Packages beziehungsweise VisualStudio Projekte unterteilt
um den Quellcode noch zusätzlich zu strukturieren. Die vier Packages
BusinessObjects, Synchronization, Exception und Utils werden in Abbildung 10
dargestellt und in folgenden Abschnitten besprochen.
Softwarearchitektur
40
ThemiSync
BusinessObjects
Synchronization
Exceptions
Utils
Abbildung 10: Komponentenarchitektur Überblick
16.1.1
ThemiSync
ThemiSync ist das Basispackage der API. Es dient als Einstiegspunkt zur
Synchronisation und delegiert Methodenaufrufe an die entsprechenden Stellen
weiter. Die wichtigsten Klassen dieser DLL sind in Abbildung 11 zu sehen:
Softwarearchitektur
41
Abbildung 11: Package ThemiSync Übersicht
ThemiSyncConfig
Diese
statische
Klasse
bietet
diverse
globale
Einstellmöglichkeiten
für
laufzeitbedingte Charakteristiken. Eine elementare Methode zum Initialisieren aller
DAC-Klassen11 stellt InitializeEntityTypes() dar. Dies wird benötigt damit
ThemiSync
an
den
entsprechenden
Stellen
über
Speichervorgänge
der
BusinessObjects informiert wird und ThemiSync-eigene Metadaten aktualisieren
kann. Durch dieses flexible Konzept ist es möglich, ohne Eingriff in die bestehende
Applikation und deren Geschäftsmodell ThemiSync zu integrieren.
ThemiSyncExport
Die Klasse ThemiSyncExport ermöglicht es unter Angabe eines Exportpfades und
der
Quelldatenbank
die
synchronisationsrelevanten
Daten
(definiert
durch
Konfigurationen, siehe 17.3) in einen Transportcontainer zu Exportieren.
11 DAC-Klassen (Data Access Class) sind hier von IBOF generierte Klassen, welche einen einfachen
Zugriff auf persistierte Datenobjekte ermöglichen. Zusätzlich bieten diese Klassen auch
Metainformationen über die korrelierenden Objekttypen welche von ThemiSync verwendet werden.
Softwarearchitektur
42
ThemiSyncImport
ThemiSyncImport obliegt das Importieren aller Daten eines Transportcontainers.
Dafür wird sowohl der Pfad zur Containerdatei als auch die Zieldatenbank benötigt.
Weiters wird über diese Klasse das gesamte Konflikthandling, welches während des
Importvorganges auftreten kann, gesteuert. Falls ThemiSync während des
Importvorgangs
einen
Konflikt
nicht
automatisiert
auflösen
kann,
weil
beispielsweise zwei abzugleichende Entitäten jeweils unabhängig ihren Zustand
geändert haben, wird der benutzerdefinierte Handler aufgerufen, sofern einer
registriert wurde und in den Einstellungen aktiviert wurde.
Zusätzlich besteht auch die Möglichkeit bei komplexen Geschäftsmodellen einen
benutzerdefinierten Speichervorgang zu verwenden.
16.1.2
BusinessObjects
Dieses Package enthält die gesamte Businesslogik von ThemiSync, welche zum
Organisieren der erforderlichen Metadaten und zur Systemkonfiguration benötigt
wird. Außerdem sind Klassen zur Protokollierung von Datenstandänderungen, so
genannte ChangeTracking-Entities beziehungsweise Tombstone-Entities enthalten.
Die Grundstruktur dieser Bibliothek wurde von IBOF generiert und ist somit
Voraussetzung einer ThemiSync erweiterten Applikation.
Softwarearchitektur
43
Abbildung 12: Datenmodell Grundstruktur
Abbildung 12 veranschaulicht die von IBOF generierten „Entity“-Klassen, welche
von IBOF aus deren entsprechenden Tabellen generiert wurden.
EntityTypeEntity
Die Klasse EntityTypeEntity bildet die synchronisierbaren Entitäts-Typen ab. Neben
der genauen Identifikation der Typen wird noch zusätzlich eine totale Ordnung
bereitgestellt um Abhängigkeiten während den Synchronisationsvorgängen einfacher
aufzulösen.
ChangeTrackingEntity
Zu jeder synchronisierbaren Entität existiert genau eine ChangeTrackingEntity
Entität, welche Metadaten, die für die Synchronisationsvorgänge benötigt werden,
enthalten. Dabei wird unter anderem der Objekt-Zustand der Entität, anhand eines
Softwarearchitektur
44
Hashcodes gespeichert. Falls eine Entität gelöscht wird, dann wird auch deren
ChangeTrackingEntity Entität gelöscht.
TombstoneEntity
Wenn eine synchronisierbare Entität gelöscht wird, dann wird eine TombstoneEntity
Entität erstellt um diesen Löschvorgang zu protokollieren und gegebenenfalls auch
auf andere Replicas anzuwenden.
ConfigurationEntity
Um Synchronisationsvorgänge vorzubereiten werden ConfigurationEntity Entitäten
benötigt,
welche
entweder
ImportConfigurationEntity
Entitäten
oder
ExportConfigurationEntity Entitäten darstellen. Dabei werden auch Einstellungen für
die Synchronisationsvorgänge festgelegt. Die Klasse ImportRuleEntity legt fest, wie
ThemiSync
bei
einem
Synchronisations-Konflikt
reagieren
soll
und
PreImportActionEntity ermöglicht Aktionen, wie das Leeren von Tabellen vor dem
Importieren durchführen zu können.
Jede sogenannte Configuration betrifft allerdings genau eine EntityTypeEntity
Entität, also genau einen synchronisierbaren Typ. Ohne Configuration Entitäten
einer EntityTypeEntity Entität ist es nicht möglich diesen Typ zu synchronisieren.
ConfigurationGroupEntity
Die Klasse ConfigurationGroupEntity wird dafür benötigt einen atomaren
Synchronisationsvorgang anhand mehrerer Configuration Entitäten durchzuführen.
ConfigurationGroupMappingEntity
Mit dieser Klasse können Verknüpfungen zwischen ConfigurationGroupEntity
Entitäten hergestellt werden, welche zum Erleichtern des Import-Vorgangs dienen.
Dadurch kann festgellegt werden welche ConfigurationGroupEntity Entity beim
Import-Vorgang automatisch angewandt wird, beim Importieren einer bestimmten
ConfigurationGroupEntity Entity.
SystemInfoEntity
Entitäten dieser Klasse beschreiben globale Informationen und Einstellungen der
ThemiSync-Instanz.
Softwarearchitektur
45
In folgender Abbildung 13 werden weitere wichtige Klassen illustriert, die sich im
Package BusinessObjects befinden.
Abbildung 13: Diverse Klassen
EntityManager
Die Klasse EntityManager stellt allgemeine Operationen bereit, die auf
synchronisierbare Entitäten angewendet werden können. Zum Beispiel das Kopieren
von Entitäten auf andere Replicas, oder aber auch das aktualisieren der
ChangeTrackingEntity Entitäten einer synchronisierbaren Entität ermöglicht diese
Klasse.
DacDependencyGraph
Diese Klasse ermöglicht die Abhängigkeiten der synchronisierbaren Entitäten zu
analysieren und mit einem Algorithmus (siehe 15.3.2) eine möglichst konfliktfreie
Import-Reihenfolge zu berechnen.
16.1.3
Synchronization
Hier findet man alle Klassen, welche für die eigentlichen Synchronisationsprozesse
und für das Handling des Transportcontainers zuständig sind. Der Großteil der
Funktionalität wird aus dem ThemiSync Package hier her delegiert.
Die bedeutendsten Klassen in dieser Bibliothek sind folgend kurz beschrieben und in
Abbildung 14 illustriert:
Softwarearchitektur
46
Abbildung 14: Datenmodell Synchronization
Import- und Exportaction
Instanzen dieser Klassen führen jeweils einen atomaren Synchronisationsprozess
durch.
Importhandler
Der Importhandler ermöglicht den Programmfluss zu bestimmten Zeitpunkten
beziehungsweise an definierten Stellen zu beeinflussen, wodurch komplexe
Geschäftsmodelle auch dann gespeichert werden können, wenn eine Gefahr auf
Datenbank-Constraint-Konflikte besteht. Als Beispiel sei hier eine zyklische
Abhängigkeit zwischen den Business Objects, welche in der Datenbank mittels
Fremdschlüssel abgebildet wurden.
DBArchive
Das DBArchive stellt im Grunde eine Virtualisierung eines Datencontainers dar und
ist für das Speichern und Laden von Transportdatenbanken zuständig. Die konkrete
Technologie zum Abbilden dieser Datenbanken in ein Dateisystem kann generisch
über den Einsatz einfacher Wrapperklassen definiert werden. Die aktuelle
ThemiSync Implementierung enthält bereits einen Wrapper für das DBMS Microsoft
SQL Server Compact.
Softwarearchitektur
16.2
47
Querschnittskomponente
Folgende Komponenten sind fachlich keinem Paket eindeutig zuordenbar und
werden von diversen anderen Komponenten referenziert:
16.2.1
Utils
Die Klassen dieser Bibliothek enthalten diverse Hilfsfunktionen, welche an mehreren
Stellen Verwendung finden. Vor allem die Third-Party Bibliotheken werden über
Klassen in diesem Package angesprochen. Folgende Abbildung 15 gibt einen kurzen
Überblick über die Klassen aus dem Package Utils.
Abbildung 15: Datenmodell Utils
16.2.2
Exceptions
Um sowohl eine Exception-Hierarchie, ausgehend von ThemiSyncException zu
gewährleisten, als auch zirkuläre Abhängigkeiten zwischen den Packages zu
vermeiden, wurden alle Exceptions in ein separates Package ausgelagert. Abbildung
16 illustriert die Exception und deren Abhängigkeiten untereinander.
Softwarearchitektur
48
Abbildung 16: Datenmodell Exceptions
16.3
Anwendungskern
Zur
Steuerung
der
Import-
und
Exportvorgänge
bildet
ThemiSync
die
Konfigurationseinstellungen in der Datenbank mit den Klassen ImportConfiguration
und ExportConfiguration ab. Wichtig ist hierbei, dass jede Konfiguration sich
eindeutig auf einen Typ der Applikations-Anwendungslogik bezieht. Für jeden Typ
können beliebig viele Konfigurationsinstanzen existieren.
Dieses Konzept erlaubt es Vorlagen für Synchronisationsprozesse einzusetzen und
ist in folgende Klassenhierarchie aufgebaut:
Softwarearchitektur
49
Abbildung 17: Configuration Klassenhierarchie - vereinfachte Darstellung
Wie in Abbildung 17 ersichtlich, besteht eine ConfigurationEntity neben einer
Beschreibung aus folgenden Attributen:
SqlWhereStatement /SqlJoinStatement
Um zu definieren welche Daten exportiert beziehungsweise importiert werden
sollen, bedient sich ThemiSync einer benutzerdefinierten Datenbankabfrage. Diese
setzt sich aus dem SqlWhereStatement und dem SqlJoinStatement zusammen.
UseTombstoneEntities
Dieses Flag entscheidet, ob gelöschte Datensätze des referenzierten Datentyps
exportiert beziehungsweise importiert werden. Wenn gelöschte Datensätze exportiert
und bei einer anderen Replica wieder importiert werden, dann werden die
betreffenden Datensätze falls kein Konflikt auftritt gelöscht. Dieses Flag dient als
Schutzmechanismus sowohl für den Export als auch für den Import.
Der Synchronisierungsprozess kann in zwei große Bereiche, Export und Import
unterteilt
werden.
Für
diese
Bereiche
gibt
es
jeweils
spezialisierte
Konfigurationsklassen, wobei nur die Importkonfiguration zusätzliche Attribute
benötigt. Zum einen gibt es das Attribut PreImportAction welches bestimmte
Softwarearchitektur
50
Operationen vor dem Import auf die entsprechende Tabelle ausführt (z.B. löschen
des gesamten Tabelleninhaltes) und zum Anderen wird im Attribut ImportRule die
Regel angegeben, welche ausgeführt wird, wenn ein Import-Konflikt auftritt. Dabei
besteht die Möglichkeit anzugeben, ob der neue oder der alte Datensatz
schlussendlich in der Datenbank gespeichert wird beziehungsweise erhalten bleibt.
Falls eine benutzerdefinierte Behandlung erforderlich ist, muss diese in der
ImportRule aktiviert werden, sodass die registrierten Methoden aufgerufen werden.
Einzelne Konfigurationsinstanzen werden zu so genannten Konfigurationsgruppen
(ConfigurationGroupEntity) zusammengefasst und stellen als solche eine atomare
Synchronisationseinheit dar. Die Gruppen sind durch einen eindeutigen Namen
definiert, welcher in den Exportdaten mitgespeichert wird. Damit ist es möglich,
beim Import automatisch die zugehörige Import-Konfigurationsgruppe auszuwählen.
Dies wird durch die Klasse ConfigurationGroupMappingEntity ermöglicht, welche
wie in folgender Abbildung 18 dargestellt in das System eingefügt ist.
Softwarearchitektur
51
Abbildung 18: Konfigurationsgruppen - vereinfachte Darstellung
16.3.1
Export
Der Exportvorgang besteht banalisiert ausgedrückt aus der Selektion für die
Synchronisation relevanten Daten und dem Erstellen eines Transport-Containers,
welcher mit den selektierten Daten befüllt wird.
Um den Exportvorgang anzustoßen, muss eine Instanz der Klasse ThemiSyncExport
erstellt werden, wofür sowohl ein Datenbankobjekt12 der Quelldatenbank
(Standardmäßig wird die IBOF Default-Database verwendet), als auch der Pfad des
resultierenden Transportcontainers benötigt wird. Der bestehenden Instanz kann nun
eine Liste von ConfigurationGroupEntities übergeben werden, welche beim
Ausführen der Methode Start() abgearbeitet wird. Dabei wird für jeden Listeneintrag
12 Hierbei ist ein Objekt vom Typ InfPro.Datenbank.Database gemeint.
Softwarearchitektur
52
eine ExportAction erstellt, welche einen atomaren Exportvorgang durchführt.
Nachdem alle Exportvorgänge durchgeführt wurden, werden die resultierenden
Datenbankfiles in einen Transportcontainer verpackt und im Dateisystem
abgespeichert (ExportPath).
Folgende Grafik (Abbildung 19) zeigt den schematischen Ablauf eines
Exportvorganges.
Datenbankfile
Für jede Konfiguration wird ein
erstellt (Access, SQL CE, …). Diese Files werden zu einem
Von IBOF unterstütztes DB-System
Transportcontainer zusammengefasst.
Datenbank
Alle Daten
Gefilterte Daten
Transportcontainer
ThemiSync-Erweiterte IBOF Applikation.
Instanz von ThemiSyncExport wird mit beliebig vielen ConfigurationGroupEntity-Entitäten initialisiert.
Abbildung 19: Ablauf Exportvorgang
16.3.2
Import
Der Importvorgang besteht, ähnlich dem Exportvorgang, aus einer Selektion der im
Transport-Container enthaltenen Daten, welche je nach Import-Konfiguration mit
ihren analogen Datensätzen der Zieldatenbank verglichen beziehungsweise behandelt
werden.
Um
einen
Importvorgang
zu
beginnen,
wird
eine
Instanz
der
Klasse
ThemiSyncImport angelegt, wofür zwingend der Pfad zum Transport-Container
benötigt wird. Sollte für den Import nicht die IBOF Standarddatenbank verwendet
werden, kann die gewünschte Zieldatenbank zusätzlich spezifiziert werden.
Mit dem Aufruf der Methode Start() wird der gesamte Inhalt des TransportContainers analysiert und für jede der darin enthaltenen Datenbanken eine Instanz
der Klasse ImportAction erstellt. Diese stellen analog zur ExportAction einen
atomaren Importvorgang dar. Während des Importvorganges wird anhand der
Importkonfigurationen und der Metadaten sowohl von der Quell-, als auch von der
Zieldatenbank, eine Selektion der importfähigen Datensätze durchgeführt.
Softwarearchitektur
53
Falls für einen Datensatz nicht automatisch entschieden werden kann, ob er
importiert werden soll oder nicht, wird ein Konfliktereignis ausgelöst, welches die
optional registrierten Ereignishandler informiert. Damit haben die Ereignishandler
die Möglichkeit benutzerdefiniert über den weiteren Synchronisationsverlauf zu
entschieden.
Eine besondere Schwierigkeit beim Importvorgang stellen komplexe Strukturen im
Datenmodell dar. So bildet IBOF Beziehungen im Geschäftsmodell anhand von
Fremdschlüsseln in der Datenbank ab. Da das temporäre Deaktivieren der
Fremdschlüssel, was ein möglicher Lösungsansatz wäre, den Speichervorgang in
seiner Performance stark beeinträchtigt, verwendet ThemiSync diverse Routinen
zum Vermeiden von Konflikten im Zusammenhang mit Fremdschlüssel. Für sehr
viele Standardfälle implementiert ThemiSync einen Algorithmus zum automatischen
Bestimmen der Speicherreihenfolge (siehe 15.3.2). Zusätzlich gibt es die
Möglichkeit diese Reihenfolge benutzerdefiniert vorzugeben.
Für zyklische Abhängigkeiten im Datenmodell genügt es nicht die Reihenfolge auf
Tabellenebene zu bestimmen, da derartige Strukturen aufgrund wechselseitiger
Referenzierenden nicht mit einer einfachen Operation in der Datenbank persistiert
werden können.
Zur Auflösung dieser Abhängigkeiten sind mehrere Lösungsansätze denkbar. Um
möglichst generisch und flexibel zu bleiben, bietet ThemiSync über PreImportEvents
beziehungsweise PostImportEvents die Möglichkeit, Abhängigkeiten vor dem
Importieren aufzulösen beziehungsweise nach dem Importieren wiederherzustellen.
Folgende Grafiken präsentieren Beispiele, welche die genannte Problematik
verdeutlichen sollen und die Entscheidung für den gewählten Lösungsansatz
begründen:
Softwarearchitektur
54
Abbildung 20: Objekthierarchie
Das dargestellte Beispiel in Abbildung 20 zeigt eine Hierarchie welche problemlos
durch Beachten der Speicherreihenfolge der einzelnen Datensätze gelöst werden
kann. Eine mögliche Reihenfolge wäre zum Beispiel: D, C, B, A
In Fällen von Assoziationszyklen oder Rekursionen wäre ein Lösungsansatz, welcher
sich rein auf die Änderung der Speicherreihenfolge beschränkt nicht ausreichend.
Mit dem PreImport- beziehungsweise PostImportEvents sind auch derartige Fälle
abzubilden, da man während eines PreImportEvents die Referenzen aushebeln kann
und diese nach dem Speichern während des PostImportEvents wieder einfügen kann.
17
Implementierungssicht
In diesem Abschnitt werden die wichtigsten Komponenten der ThemiSync API aus
implementierungstechnischer Sicht beleuchtet.
17.1
Initialisierung
Um ThemiSync verwenden zu können, müssen beim Applikationsstart alle
synchronisierbaren
DAC-Klassen
der
Methode
Initialize()
der
Klasse
ThemiSyncConfig übergeben werden. Hierbei wird empfohlen, dass die DACKlassen mit dem Methodenaufruf
DatabaseManager.Instance.GetAllRegisteredDACClasses()
ermittelt werden.
Softwarearchitektur
55
Die Initialize-Methode überprüft das IBOF-Flag IsUsedForSynchronization und
registriert einen Eventhandler für das Ereignis BeforeSave, falls dieses auf True
gesetzt ist. Dadurch werden nur Klassen, welche für die Synchronisierung
vorgesehen sind überwacht.
Die
übergebenen
DAC-Klassen
werden
für
die
weitere
Verwendung
zwischengespeichert. Bei erstmaliger Initialisierung wird die Tabelle EntityType
aufgebaut und die Abhängigkeiten in der Business-Logik automatisch aufgelöst,
indem die Speicherreihenfolge der Entitäts-Typen berechnet wird. Um die
Berechnungen später erneut durchzuführen – wegen eventuell geänderten
beziehungsweise erweiterten Tabellenstrukturen – muss das Flag CleanEntityTypes
in der Tabelle SystemInfo den Wert True erhalten. Nach erneutem Initialisieren der
DAC-Klassen, wird das Flag wieder zurück auf False gesetzt.
Softwarearchitektur
56
Klassen, die in diesem Implementierungs-Abschnitt eine Rolle spielen werden in
folgender Abbildung 21 in Form eines Klassendiagramms dargestellt:
Abbildung 21: Klassendiagramm Initialisierung
Softwarearchitektur
17.1.1
57
Ablauf
Folgendes Sequenzdiagramm in Abbildung 22 visualisiert einen vollständigen
Initialisierungsablauf, welcher konfigurationsabhängig beim Start einer ThemiSyncerweiterten IBOF-Applikation ausgeführt wird.
Program
:ThemiSyncConfig
:DacDependencyGraph
:EntityTypeDAC
Initialize(db, dacs)
InitializeEntityTypes(db, dacs)
updateResolutionSequence(db, dacs)
ResolveDependencyOrder(dacs)
orderedDacs
createAllChangeTrackingData(db, dacs)
Abbildung
22:
Sequenzdiagramm
zum
Visualisieren
eines
vollständigen
Initialisierungsvorgangs
Beim Start einer ThemiSync-erweiterten IBOF-Applikation müssen die DACKlassen aller synchronisierbaren Entitäten als Liste der Methode
public static void Initialize (Database database,
List<IBusinessObjectDAC> iBusinessObjectDACLst)
übergeben werden. Diese Methode überprüft die Kompatibilität der übergebenen
Klassen zu ThemiSync. Hierbei wird überprüft, ob ein Primärschlüssel existiert,
dieser aus genau einem Attribut besteht und den C#-Datentyp Guid besitzt. Falls eine
der Klassen die genannten Kriterien nicht erfüllt, wird eine ConfigurationException
geworfen. Anderenfalls werden die Klassen über die EntityTypeDAC SingletonInstanz verarbeitet.
Softwarearchitektur
58
Die Methode
public void InitializeEntityTypes(Database database,
List<IBusinessObjectDAC> iBusinessObjectDACs)
erstellt zu jedem Eintrag der Liste iBusinessObjectDACs eine entsprechende
EntityType Entität und macht diese über einen Cache applikationsweit zugänglich.
Hierbei werden die von IBOF bereitgestellten Informationen (Namespace,
Klassenname)
über
die
zugehörige
DAC-Klasse
verwendet.
Die
Klasse
EntityTypeEntity besitzt folgende Attribute, welche zum eindeutigen Zuordnen der
synchronisierbaren Entitäten zu deren entsprechenden Datentypen bestimmt sind:
EntityTypeID
Primärschlüssel vom C# Datentyp short. Dieser Datentyp wurde gewählt, da
die
unterschiedlichen
Datentypen
beziehungsweise
Klassen
in
Geschäftsmodellen dadurch effizient abbildbar sind.
EntityName
Bezeichnet den Klassenname des abgebildeten Datentyps.
EntityNamespace
Bezeichnet den C# Namespace.
ResolutionSequenceNumber
Speichert die Abarbeitungsreihenfolge für Synchronisationsvorgänge.
Folgende Auflistung beschreibt weitere Attribute und Methoden der Klasse
EntityTypeDAC:
createNewEntityType
Private
Methode,
welche
aus
den
übergebenen Parametern eine EntityType
Entität in der spezifizierten Datenbank
erstellt und zurück gibt.
GetEntityType
Öffentliche Methode, welche den passenden
EntityType Objekt zum übergebenen C#Datentyp
zurück
beachten,
dass
gibt.
nur
Hierbei
EntityType
ist
zu
Objekte
zurückgegeben werden, welche aus der
Softwarearchitektur
59
Standard-Datenbank stammen.
GetTypeToEntityType
Öffentliche
übergebenen
Methode,
welche
EntityType
aus
Entität
der
den
dazugehörigen Datentyp zurück gibt. Hierbei
ist zu beachten, dass nur Datentypen zu
EntityType Entitäten der Standard-Datenbank
zur Verfügung stehen.
GetTypeToEntityTypeID
Diese öffentliche Methode verhält sich
analog zur Methode GetTypeToEntityType.
Allerdings wird hier der primitive Datentyp
short
übergeben,
Probleme
wodurch
mit
eventuelle
unterschiedlichen
Datenbanken13 vermieden werden können.
FindByEntityNameAndNameSpace
Öffentliche Methode, welche die bereits von
IBOF angebotenen Find-Methoden erweitert,
sodass bequem nach EntityType Entitäten
mittels
Klassenname
und
Klassen-
Namespace gesucht werden kann. Durch
diese beiden Parameter sind alle EntityType
Entitäten eindeutig spezifiziert.
FindByAbstractBusinessObject
Öffentliche Methode, welche die zugehörige
EntityType Entität zu dem übergebenen
AbstractBusinessObject zurück gibt.
Aufgrund der Abhängigkeiten der BusinessObjects ist eine bestimmte Sequenz beim
Persistieren nötig. Diese wird nach dem Erstellen aller EntityType Entitäten
automatisiert von der Methode
13 Problem mit unterschiedlichen Datebanken können auftreten falls mehrere EntityType Entitäten
aus verschiedenen Datenbanken stammen, und daher im Cache nicht mehr eindeutig zugeordnet
werden können.
Softwarearchitektur
60
private void updateResolutionSequence(Database database,
List<IBusinessObjectDAC> dacs)
aktualisiert. Die eigentliche Berechnung einer korrekten Sequenz erfolgt in der
Klasse DacDependencyGraph.
Nachdem die EntityType Entitäten erstellt, und deren Abhängigkeiten aufgelöst
wurden, werden die ChangeTracking Entitäten in folgender Methode erstellt:
private void updateResolutionSequence(Database database,
List<IBusinessObjectDAC> dacs)
Sowohl die Auflösung der Abhängigkeiten, als auch das Erstellen der fehlenden
ChangeTracking Entitäten werden im Falle von bereits bestehenden EntityType
Entitäten inkrementell auf DAC-Klassen, welche nach der Erst-Initialisierung als
synchronisierbar markiert wurden, ausgeführt. Eine vollständige Neu-Initialisierung
der EntityType Entitäten, welche beim Deaktivieren von synchronisierbaren
BusinessObjects die Datenbank bereinigt, wird über eine Entität des Typs
SystemInfoEntity angestoßen (Siehe 27.5).
Um in der ThemiSync-API auf Änderungs- beziehungsweise Speichervorgänge in
der Business-Logik reagieren zu können, ohne Änderungen am Quellcode von
ThemiSync-erweiterten IBOF-Applikationen vornehmen zu müssen, bedient sich
ThemiSync dem Event-Konzept von C#. Aus diesem Grund wird abschließend die
Methode
public static void UpdateMetaData(object sender,
AbstractBusinessObjectsEventArgs e)
der Klasse EntityManager für die Speicher-Events BeforeSave, welche in den von
IBOF bereitgestellten DAC-Klassen angeboten werden.
17.2
Metadaten
Die Implementierung des Synchronisationsalgorithmus von ThemiSync (beschrieben
in 15.3.1) verwendet sogenannte Metadaten, auf deren Erstellung und Verwaltung in
den folgenden Abschnitten eingegangen wird.
Softwarearchitektur
17.2.1
61
Metadaten Struktur
Abbildung 23: Datenmodell Metadaten-spezifische Klassen
Eine Übersicht über die Klassen, welchen Metadaten-spezifische Bedeutungen
zukommen, bietet Abbildung 23.
Die ThemiSync-API benötigt verschiedene Metadaten um den verwendeten
Synchronisationsalgorithmus
(siehe
15.3.1)
durchführen zu können.
Diese
Softwarearchitektur
62
Informationen werden in Tabellen eines ThemiSync-spezifischen Datenbankschemas
gespeichert,
um
möglichst
wenige
Anpassungen
auf
bereits
bestehende
Anwendungen und deren Geschäftsmodell nötig zu machen.
Änderungen an synchronisierbaren Entitäten werden mit ChangeTrackingEntity
Entitäten erfasst. Zu jeder synchronisierbaren Entität existiert genau eine
ChangeTrackingEntity Entität, welche den aktuellen Objektzustand anhand eines
Hashcodes im Attribut EntityHash abbildet. Der Hashcode des letzten synchronen
Objektzustandes wird im Attribut LastSyncHash gespeichert. Diese beiden Attribute
erlauben dem Synchronisationsalgorithmus die direkte Entscheidung, ob die Entität
importiert werden kann, oder ob ein Konflikt-Ereignis auftritt. Das boolesche
Attribut LocallyChanged zeigt an, ob sich die Entität seit der letzten Synchronisation
geändert
hat.
Es
wird
bei
der
jeweils
ersten
Änderung
nach
einem
Synchronisationsprozess auf True gesetzt und verhindert damit das erneute
Überschreiben des LastSyncHashs bei weiteren Änderungen. Damit in einer
zentralen Tabelle alle Entitäten tabellenübergreifend abgebildet werden können,
werden die folgenden zwei Attribute benötigt:
EntityID
Speichert die eindeutige ID14 der referenzierten Entität.
EntityTypeID
Beschreibt die Entitätsklasse mittels Verweis auf die entsprechende
EntityType Entität.
Werden synchronisierbare Entitäten gelöscht, so muss ThemiSync dies mitprotokollieren, um bei der Synchronisation entsprechend darauf reagieren zu können.
Diese Informationen werden in TombstoneEntity Entitäten gespeichert. Hierbei wird
analog zur ChangeTrackingEntity die gelöschte Entität mittels EntityID und
EntityTypeID eindeutig identifiziert.
14 Im Rahmen des Projektes kann davon ausgegangen werden, dass jeder Datensatz mit einem
Primärschlüssel des C# Datentyps Guid (Global Unique Identifier) Replica-weit eindeutig ist.
Softwarearchitektur
17.2.2
63
Aktualisierung der Metadaten
Die Aktualisierung der Metadaten erfolgt bei jedem Speichervorgang einer
synchronisierbaren Entität. Mit der Registrierung des Ereignisses OnBeforeSave
während der Initialisierung von ThemiSync wird unmittelbar vor dem Speichern der
Entität in der Datenbank die statische Methode
public static void UpdateMetaData(object sender,
AbstractBusinessObjectsEventArgs e)
der Klasse EntityManager ausgeführt.
Beim Speichervorgang jedes AbstractBusinessObjects15 wird von IBOF entschieden,
ob die Entität in der Datenbank erstellt, geändert oder gelöscht werden soll. Für die
Methode UpdateMetaData ist in erster Linie interessant, ob die Entität gelöscht
werden soll oder in der Datenbank erhalten bleibt.
Falls
die
Entität
nicht
gelöscht
wird,
dann
wird
die
zugehörige
ChangeTrackingEntity Entität aktualisiert oder neu erstellt, sofern diese noch nicht
existiert. Liegt eine Änderung vor, dann wird anhand des LocallyChanged-Flags
überprüft, ob es die erste Änderungen nach dem letzten Synchronisationsvorgang ist.
Ist dies der Fall, so wird der LastSyncHash mit dem CurrentHash vor der Änderung
überschrieben. In jedem Fall wird der CurrentHash abschließend an den aktuellen
Objektzustand angepasst.
Wird die Entität allerdings gelöscht, so ist eine bereits bestehende, zugehörige
ChangeTrackingEntity Entität ebenfalls aus der Datenbank entfernt. Um den
Löschvorgang zu protokollieren wird eine TombstoneEntity Entität erstellt und in der
Datenbank persistiert.
Es kann vorkommen, dass eine Entität gelöscht wird und zu einem späteren
Zeitpunkt wieder importiert wird. Wenn diese Entität erneut gelöscht wird, dann
wird keine zusätzliche TombstoneEntity Entität erzeugt.
15 AbstractBusinessObject ist der Basisdatentyp aller von IBOF generierten, persistierbaren Entitäten.
Softwarearchitektur
17.2.3
64
Hashcode-Berechnung
Um den aktuellen Objektzustand einer synchronisierbaren Entität effizient und
platzsparend abzubilden, wird über alle persistierbaren Properties ein eindeutiger
Hashcode erstellt. In der aktuellen Implementierung wird dafür der Algorithmus
MD516 verwendet.
Um die Daten für die Hashcode-Generierung aufzubereiten, wurde eine eigene
Methode für die Serialisierung entwickelt. Obwohl eine entsprechende Methode von
C# bereits nativ angeboten wird, wurde die statische Methode
public static byte[] Serialize(AbstractBusinessObject obj)
der
Klasse
IbofHashFormatter
selbst
implementiert.
Dies
wurde
aus
Effizienzgründen gemacht, da von IBOF entsprechende Metadaten zur Verfügung
stehen, um die Serialisierung ohne aufwendige Reflections (siehe 13) durchzuführen.
Außerdem konnte dadurch die Serialisierung exakt auf die Bedürfnisse der
synchronisierbaren Entitäten angepasst werden.
Serialize() verwendet von IBOF angebotene Metadaten um alle Entitäts-relevanten
Werte in einem Byte-Array abzubilden.
Die endgültige Verarbeitung des Byte-Arrays zum Hashcode erfolgt in der statischen
Methode
public static Guid GenerateHashCode(AbstractBusinessObject
businessObject)
der Klasse IbofHashGenerator. Der berechnete Hashcode wird in Form des Typs
Guid zurückgegeben, da dies ein primitiver C# Datentyp ist, und somit effizient
weiterverarbeitet werden kann.
17.2.4
Beschreibung weiterer Klassen
Weitere Metadaten-bezogene Methoden und Klassen werden folgend tabellarisch
aufgelistet und beschrieben. Die Auflistung enthält nur relevante Inhalte und ist nicht
vollständig.
16 Message-Digest Algorithm
Softwarearchitektur
65
EntityManager
public static void
SaveToSpecifiedDatabase(
AbstractBusinessObject,
Diese Methode erlaubt das einfach Kopieren
eines
AbstractBusinessObjects
in
eine
Database,
spezifizierte Datenbank (Parameter vom Typ
IBusinessObjectDAC)
InfPro.Datenbank.Database).
Diese
Methode
wird sowohl beim Exportieren als auch beim
Importieren verwendet.
public static void Update(
AbstractBusinessObject,
ChangeTrackingEntity,
Diese Methode ersetzt eine Entität und die
dazugehörige
ChangeTrackingEntity-Entität
AbstractBusinessObject,
(ersten zwei Parameter) mit einer neuen Entität
ChangeTrackingEntity)
beziehungsweise
ChangeTrackingEntity-Entität
(letzen zwei Parameter). Diese Methode findet bei
Importkonflikten
ihren
Einsatz
falls
die
bestehende Entität überschrieben werden soll.
public static
ChangeTrackingEntity
CreateMetadata(
Database,
Erstellt die erforderlichen Metadaten für eine
Entität
(AbstractBusinessObject)
in
der
übergebenen Datenbank (Database).
AbstractBusinessObject)
ChangeTrackingDAC
Public ChangeTrackingEntity
FindByAbstractBusinessObject(
Database,
AbstractBusinessObject)
Diese
Methode
findet
die
passende
ChangeTrackingEntity-Entität zur übergebenen
AbstractBusinessObject-Entität.
Wird
kein
passender Eintrag gefunden, so gibt sie null
zurück. Bei mehrfacher Existenz wird eine
CorruptMetadataException geworfen.
Public ChangeTrackingEntity
FindByEntityIDAndTypeUnique(
Databas,Guid, short)
Findet
die
passende
ChangeTrackingEntity-
Entität in einer Datenbank (Database) anhand
ihrer eindeutigen ID (Guid) und der EntityType-
Softwarearchitektur
66
ID.
EntityTypeDAC
public EntityTypeEntity
GetEntityType(Type type)
Gibt die EntityTypeEntity-Entität zu einem Typ
zurück. Dabei ist kein Zugriff auf die Datenbank
nötig, da sich alle registrierten Typen in einem
Cache
befinden,
welcher
in
der
Methode
InitializeEntityTypes() (siehe unten) befüllt wird.
public Type
GetTypeToEntityType(EntityTyp
eEntity EntityType)
Gibt den Typ zu einer EntityTypeEntity-Entität
zurück. Dabei ist kein Zugriff auf die Datenbank
nötig, da sich alle registrierten Typen in einem
Cache
befinden,
welcher
in
der
Methode
InitializeEntityTypes() (siehe unten) befüllt wird.
public void
InitializeEntityTypes(
Database,
List<IBusinessObjectDAC>)
Diese Methode muss bei jeder ThemiSyncerweiterten
IBOF
ausgeführt
werden,
Applikation
falls
dort
einmalig
ThemSync-
Funktionalität benötigt wird. Sie läuft alle
Einträge
der
übergebenen
(List<IBusinessObjectDAC>)
Liste
durch
und
überprüft, ob dazu bereits ein Eintrag in der
Datenbank (Database) existiert. Ist dies der Fall,
so wird dieser in einen Cache geladen, andernfalls
wird er vorher erstellt und persistiert.
Befindet sich in der Datenbanktabelle SystemInfo
ein Eintrag CleanEntityTypes mit dem Wert True,
so werden nicht-referenzierte Einträge gelöscht
und
neu
erstellt.
Dies
ist
bei
einer
Modelländerung nötig.
private void
createAllChangeTrackingData(D
Diese Methode erstellt für alle persistierten
Softwarearchitektur
atabas,
List<IBusinessObjectDAC>)
67
Instanzen
der
übergebenen
Typen
(List<IBusinessObjectDAC>)
eine
ChangeTrackingEntity-Entität in der Datenbank
(Database) falls diese nicht existiert.
Befindet sich in der Datenbanktabelle SystemInfo
ein Eintrag CleanEntityTypes mit dem Wert True,
so
wird
diese
Methode
von
der
vorher
beschriebenen Methode InitializeEntityTypes()
aufgerufen.
private void
updateResolutionSequence(
Database,
List<IBusinessObjectDAC>)
In dieser Methode
Reihenfolge
der
wird die hierarchische
Übergebenen
Typen
(List<IBusinessObjectDAC>) berechnet um bei
Importvorgängen Probleme mit Fremdschlüsseln
zu vermeiden (siehe 15.3.2).
17.3
Konfiguration
Im folgenden Abschnitt werden die Konfigurationsklassen von ThemiSync näher
beschrieben, welche dem Anwendungsentwickler für die unterschiedlichen
Synchronisationsszenarien zur Verfügung stehen. Alle diese Konfigurationen werden
in der Datenbank persistiert und dienen als Konfigurations-Vorlagen, wodurch es
möglich ist beliebig viele Konfigurationen vorzubereiten. Abbildung 24 gibt einen
Überblick über die Klassen, welche für die Konfiguration relevant sind.
Softwarearchitektur
68
Abbildung 24: Konfiguration Technisches Klassendiagramm
17.3.1
Allgemeine Struktur
Die
Konfigurationen
für
einen
atomaren
in
sich
abgeschlossenen
Synchronisationsvorgang werden in einer sogenannten ConfigurationGroupEntity
Entität gekapselt. Eine ConfigurationGroupEntity Entität besitzt folgende relevante
Attribute:
Name
Eine eindeutige Bezeichnung der Konfigurationsgruppe.
Description
Eine informative Beschreibung der Konfigurationsgruppe.
Softwarearchitektur
69
Eine ConfigurationEntity Entität beschreibt eine Vorlage für die Synchronisierung
einer einzelnen Entitäts-Klasse. Sie dient als Basisklasse sowohl für Export- und
Importkonfigurationen und besitzt folgende relevante Attribute:
ConfigurationGroupID
Die Referenz auf die zugehörige ConfigurationGroupEntity Entität.
EntityTypeID
Da jede ConfigurationEntity Entität als Vorlage für eine bestimmte EntitätsKlasse
definiert
wird,
ist
eine
Referenz
auf
die
entsprechende
EntityTypeEntity Entität notwendig.
Description
Eine informative Beschreibung der Konfiguration.
SqlWhereClause
Dieses Attribut ist ein elementares Konstrukt zum Filtern der Export- oder
Importdaten, welches SQL Code enthält, welcher auf die entsprechende
Datenbank direkt angewandt wird. Obwohl die Konfiguration dadurch
datenbankabhängigen
Code
Datenbanksystemunabhängigkeit
enthält,
beeinträchtigt
von ThemiSync nicht,
dies
die
da für
alle
unterschiedlichen Anwendungsszenarien eine passende Konfiguration erstellt
werden kann. Um mit einer einzigen Konfiguration möglichst viele Fälle
abdecken zu können, bietet das Attribut SqlWhereClause die Möglichkeit
mittels der Template-Engine NVelocity [San 09] Vorlagen zu erstellen. Der
dadurch entstandene SQL Code filtert die Daten anhand einer WHEREKlausel [KemEik 06], welche mit einem entsprechenden SELECT-Statement
[KemEik 06] konkateniert wird.
SqlJoinStatement
Dieses Attribut dient zum Tabellenübergreifenden Filtern von Export- oder
Importdaten, welches analog zum SqlWhereClause Attribut verwendet
werden kann.
UseTombstoneEntities
Mit diesem Attribut wird angegeben, ob beim Export- oder Importvorgang
gelöschte Entitäten berücksichtigt werden. Damit ist es möglich das
Entfernen von Entitäten beim Synchronisationsvorgang zu verhindern.
Softwarearchitektur
17.3.2
70
Export Struktur
Für die Steuerung von Export-Vorgängen sind ExportConfigurationEntity Entitäten
zuständig.
ExportConfigurationEntity
Entitäten
besitzen
keine
weiteren
Ausprägungen im Vergleich zu ConfigurationEntity Entitäten, trotzdem ist eine
Markierung als Exportkonfiguration von fundamentaler Bedeutung für ThemiSync,
um die Konfigurationen unterscheiden zu können.
17.3.3
Import Struktur
Eine ImportConfigurationEntity Entität dient als Konfiguration für Importvorgänge
und erweitert eine ConfigurationEntity Entität mit folgenden Attributen:
ImportRuleID
Die gewählte Einstellung entscheidet darüber, ob bei einem Konflikt während
des Importierens die betroffene Entität der Ziel-Replica überschrieben wird
(Overwrite), erhalten bleibt (KeepExisting) oder von der Anwendungslogik
der Applikation verarbeitet wird (ApplicationDefined).
PreImportActionID
In manchen Situationen ist es nötig, alle bereits existierenden Entitäten der
Ziel-Replica vor dem Datenimport zu löschen (Delete). Standardmäßig wird
allerdings keine Aktion durchgeführt (Nothing).
Über eine Entität vom Typ ConfigurationGroupMapping kann zu einer ExportKonfiguration eine passende Import-Konfiguration definiert werden. Beim
Importvorgang werden die exportierten ConfigurationGroupEntity Entitäten
durchlaufen und jeweils durch die zugeordnete ConfigurationGroupEntity Entität
importiert.
Die Zuordnung zwischen Export- und Importkonfigurationsgruppen erfolgt aus
Benutzerfreundlichkeitsgründen über das Attribut ExportConfigurationGroupName.
Um nun die exportiere Konfigurationsgruppe einer Importkonfigurationsgruppe
zuzuordnen verweist das Attribut ConfigurationGroupID auf die entsprechende
ConfigurationGroupEntity Entität.
Softwarearchitektur
17.4
71
Synchronisation
Im folgenden Abschnitt wird auf die verschiedenen Bereiche und Phasen der
Synchronisation eingegangen.
17.4.1
Datenselektion
Unter Datenselektion wird zum Einen die Filterung der zu exportierenden Daten aus
der Quell-Replica und zum Anderen die Filterung der zu importierenden Daten aus
dem Transportcontainer verstanden. Die Steuerung der Datenselektion obliegt den
vom Entwickler zu erstellenden ImportEntity- beziehungsweise ExportEntityEntitäten. Die Attribute SqlWhereClause und SqlJoinStatement der jeweiligen
Konfigurations-Entität selektieren über einen IBOF WhereFinder17 die gewünschten
Daten.
Um die Import- beziehungsweise Export-konfigurationen möglichst flexibel zu
halten, besteht die Möglichkeit in der Property SqlWhereClause NVelocityVariablen zu verwenden. Über die öffentliche Methode RegisterVelocityVariable()
der Klasse VelocityManager können applikationsseitig die benötigten Variablen
registriert werden. Diese Methode erhält als Parameter einen String, welcher die
Variablenbezeichnung definiert und ein Delegate [Tro 07], welches die dynamisch
auszuführende Methode beschreibt. Durch die Verwendung von Delegates ist es
möglich, während des Export- beziehungsweise Importvorgangs Methoden
auszuführen, welche in der ThemiSync-Erweiterten Applikation implementiert
wurden.
ThemiSync
bietet
für
jede
Konfigurationsgruppe
einen
eigenen
VelocityManager. Außerdem können Velocity-Variablen global registriert werden.
Diese Variablen stehen allen Konfigurationsgruppen einer ThemiSyncImportbeziehungsweise ThemiSyncExport-Entität während des Synchronisationsvorganges
zur Verfügung.
Folgendes Beispiel beschreibt einen Selektionsvorgang beim Exportieren und
verwendet ThemiSync Objekte, die in Abbildung 25 und Abbildung 26 illustriert
sind:
17 IBOF WhereFinder ist ein von IBOF zur Verfügung gestelltes Werkzeug um über eine Where-
Klausel und ein Join-Statement BusinessObject Entitäten zu filtern.
Softwarearchitektur
72
ExportConfigurationEntityObj : ExportConfigurationEntity
...
SqlWhereClause : string = TypB.id in (#foreach($var in $IdLst) $var, #end 6)
SqlJoinStatement : string = JOIN TypB on TypB.x = TypA.x
EntityTypeObj : EntityTypeEntity = TypA
...
Abbildung 25: Beispiel für ein ExportConfigurationEntity Objekt
VelocityManagerObj : VelocityManager
velocitynamePropertynameDictionary = "IdLst" -> {1,2,3}
Abbildung 26: Beispiel für ein VelocityManager Objekt
Diese Exportkonfiguration soll alle Datensätze der Datenbanktabelle vom TypA
selektieren, welche einen Fremdschlüssel in der Tabelle TypB und dort die
Datensatz-ID 1,2,3 oder 6 haben.
Dies geschieht in zwei Schritten. Zuerst wird mit dem Aufruf
VelocityManagerObj.Evaluate(ExportConfigurationEntityObj.SqlWhereC
lause)
die Property SqlWhereClause ausgewertet. Das Ergebnis (“TypB.id in (1,2,3,6)”)
und das SqlJoinStatement wird an einen IBOF WhereFinder übergeben. Dieser kennt
den Typ durch das EntityTypeObj und gibt das Ergebnis zu folgendem SQL Query
zurück:
Select * FROM TypeA JOIN TypB on TypB.x = TypA.x WHERE TypB.id in
(1,2,3,6).
17.4.2
Export
Folgende Abbildung 27 zeigt ein Klassendiagramm, in welchem die wichtigsten
Klassen, die für den Exportvorgang eine bedeutende Rolle spielen, dargestellt
werden.
Softwarearchitektur
73
Abbildung 27: Klassendiagramm Export
Um
einen
Exportvorgang
ThemiSyncExport
erstellt
einzuleiten,
werden.
Diese
muss
bietet
eine
Instanz
mehrere
der
Klasse
unterschiedliche
Konstruktoren an, mit denen die Quelldatenbank in Form einer Instanz der IBOFKlasse Database und der Pfad für die Exportdatei definiert werden kann.
Die Klasse enthält eine Liste mit dem Namen ConfigurationGroups, welche mit den
zu exportierenden Konfigurationsgruppen gefüllt werden muss. Diese Liste wird
Softwarearchitektur
74
beim Ausführen der Methode Start() durchlaufen und verarbeitet. Dabei wird für
jeden Listeneintrag eine eigene Transport-Datenbank erstellt, welche durch eine
ExportAction-Instanz befüllt wird.
Um eine Instanz der Klasse ExportAction zu erstellen, müssen dem Konstruktor
folgende Parameter übergeben werden:
Database sourceDatabase
Als Parameter wird eine Instanz der IBOFKlasse Database, welche als Schnittstelle zur
Quelldatenbank dient, benötigt.
Database destinationDatabase
Als Parameter wird eine Instanz der IBOFKlasse Database, welche als Schnittstelle zur
Zieldatenbank dient, benötigt.
ConfigurationGroupEntity
configurationGroup
Als Parameter wird eine Instanz der Klasse
ConfigurationGroupEntity benötigt, welche
die zu exportierende Konfigurationsgruppe
beschreibt.
TSVelocityManager
velocityManager
Als Parameter wird eine Instanz der Klasse
TSVelocityManager benötigt, welche zum
Auswerten der SQL-Statementes benötigt
wird.
Die Hauptfunktionalität eines Exportvorgangs liegt in der Methode
public void Export()
welche sich in der Klasse ExportAction befindet. Diese Methode wird im folgenden
Abschnitt detailliert behandelt:
Der vollständige Export-Prozess wird innerhalb von Datenbank-Transaktionen
atomar durchgeführt. Zu Beginn werden globale System-Informationen des
exportierenden ThemiSync-Systems als Entitäten der Klasse SystemInfoEntity in die
Export-Datenbank gespeichert. Diese dienen zur Kompatibilitäts-Kontrolle während
Softwarearchitektur
75
des Import-Vorganges. Weiters wird auch der Name der Konfigurationsgruppe
protokolliert,
um
beim
Konfigurationsgruppe
Importieren automatisiert
verwenden
die zugehörige
zu
Import-
können
(siehe
ConfigurationGroupMappingEntity in 17.3).
Anschließend
werden
alle
ExportConfigurationEntity
Entitäten
der
ConfigurationGroupEntity Entität einzeln durchlaufen und auf jeder dieser Entitäten
die Methode FindUntyped() aufgerufen. Diese von IBOF bereitgestellte Methode
sucht anhand übergebener Parameter die passenden Einträge. Da zur Compile-Zeit
die Typen der ExportConfigurationEntity Entitäten nicht bekannt sein können, muss
diese generische Methode verwendet werden, welche Entitäten des Typs
AbstractBusinessObject zurückgibt.
Die zurückgelieferten AbstractBusinessObjects werden in die Export-Datenbank mit
deren angepassten ChangeTrackingEntity Entitäten kopiert.
Falls bei einer ExportConfigurationEntity Entität die boolesche Variable
UseTombstoneEntities den Wert True enthält, werden auch die für diese ExportKonfiguration gefundenen TombstoneEntity Entitäten in die Export-Datenbank
kopiert.
Nachdem eine komplette ConfigurationGroupEntity Entität, wie im vorigen
Abschnitt beschrieben, verarbeitet wurde, wird in der Start() Methode der Klasse
ThemiSyncExport anschließend die resultierende Export-Datenbank in einen Filebasierten Transport-Container gespeichert. Ein Transport-Container kann mehrere
Export-Datenbanken
enthalten.
Um
beim
Einsatz
der
File-basierten
Datenbanksysteme flexibel zu bleiben, werden ein Transport-Container und dessen
Inhalte im Hauptspeicher in Form von Objektinstanzen dargestellt.
Mit diesem Konzept ist es über die Implementierung der Klasse AbstractDBWrapper
jederzeit möglich, die angebotenen Datenbanksysteme für die Export-Datenbank zu
erweitern. Die aktuelle Implementierung von ThemiSync bietet mit der Klasse
SqlCeDBWrapper die Verwendung von Microsoft SQL Compact Datenbanken an.
Softwarearchitektur
76
Als Container für die exportierten Datenbanken agiert die Klasse DBArchive, welche
die Möglichkeit bietet ihren Inhalt als ZIP-Archiv18 im Dateisystem abzulegen.
Folgende Darstellung in Abbildung 28 verdeutlicht die beschriebene ContainerStruktur anhand eines Klassendiagramms.
18 Das Dateiformat ZIP dient zum Komprimieren von mehreren Dateien und Dateistrukturen in einer
einzelnen Datei.
Softwarearchitektur
77
Abbildung 28: Datenmodell Transport-Container
Abbildung 29 beschreibt den Export-Vorgang anhand eines Sequenzdiagramms. Die
Abbildung wird aus Gründen der Übersichtlichkeit im Querformat dargestellt.
Softwarearchitektur
Abbildung 29: Sequenzdiagramm zum Visualisieren des Exportvorgangs (Querformat)
78
Softwarearchitektur
17.4.3
79
Import
Folgende Abbildung 30 visualisiert die wichtigsten Klassen für den Importvorgang
anhand eines Klassendiagramms.
Abbildung 30: Klassendiagramm Import
Softwarearchitektur
80
Ein Importvorgang kann mit einer Instanz der Klasse ThemiSyncImport gestartet
werden. Folgende Parameter können dem Konstruktor übergeben werden:
Database destinationDatabase
Als Parameter wird eine Instanz der IBOFKlasse Database, welche als Schnittstelle zur
Zieldatenbank dient, benötigt.
string sourceArchivePath
Als Parameter wird der Pfad zum exportieren
Transport-Container benötigt (siehe 17.4.2).
Wird für den Parameter destinationDatabase kein Wert übergeben, so wird die
Standarddatenbank als Ziel-Replica verwendet.
Der Importvorgang wird mit dem Aufruf der Methode Start() durchgeführt. Dabei
wird für jede Datenbank, die sich im Transport-Container befindet, eine neue Instanz
der Klasse ImportAction erstellt. Die Methode Import() der Klasse ImportAction
führt den Importvorgang für die Entitäten der betreffenden Datenbank durch. Die
dafür benötigten Informationen werden dem Konstruktor von ImportAction hierfür
übergeben.
Zu Beginn werden die SystemInfoEntity Entitäten der Quell- und Ziel-Replicas
ausgelesen und verglichen, sodass sichergestellt werden kann, ob die Datenbankund ThemiSync-Versionen kompatibel zueinander sind. Weiters wird der Name der
Konfigurationsgruppe ausgelesen und durch ConfigurationGroupMappingEntity
Entitäten die zugehörige Import-Konfigurationsgruppe gesucht. Wenn eine solche
passende Konfigurationsgruppe gefunden wurde, dann werden in der Methode
Import() zusätzlich folgende drei Methoden ausgeführt:
1. runPreImportActions()
2. runTombstoneActions()
3. runImportActions()
Durch die Methode runPreImportActions() können spezielle Aktionen durchgeführt
werden, bevor der eigentliche Importvorgang begonnen hat. Derzeit werden von
ThemiSync lediglich die Aktion Nothing und Truncate unterstützt. Truncate
ermöglicht das vollständige Löschen der betreffenden Tabellen.
Softwarearchitektur
81
Die Methode runTombstoneActions() dient zum Synchronisieren von gelöschten
Entitäten. Das bedeutet, dass eventuell Entitäten auf der Ziel-Replica entfernt
werden, wenn sie auch auf der Quell-Replica entfernt und synchronisiert wurden.
Das eigentliche Importieren der Entitäten, sowie die Konfliktüberprüfung erfolgt in
der
Methode
runImportActions().
Falls
ein
Konflikt
auftretet
und
eine
benutzerdefinierte Konfliktbehandlung konfiguriert wurde, dann wird folgendes
Ereignis eintreten:
EventHandler<ConflictEventArgs>
Conflict;
Das Ereignis Conflict wird immer dann
ausgelöst, wenn beim Importieren ein
Synchronisationskonflikt auftritt.
Beim Auslösen des Conflict Ereignisses wird eine Instanz der Klasse
ConflictEventArgs mitgesendet, welche folgende Properties besitzt:
AbstractBusinessObject SourceEntity
Analoge Entität zur DestinationEntity,
welche aus dem Transport-Container
stammt. Dies ist die neue Entität, die
aus der Quell-Replika stammt.
AbstractBusinessObject
DestinationEntity
Analoge
Entität
zur
SourceEntity,
welche bereits in der Ziel-Replica
existiert.
Guid SourceReplicaID
Diese Property enthält die ID der
Quell-Replica.
Guid DestinationReplicaID
Diese Property enthält die ID der ZielReplica.
bool ImportSourceEntity
Diese Property entscheidet, ob die
betreffende
Quell-Entität
importiert
wird (True), oder die bestehende ZielEntität erhalten bleibt (False).
Softwarearchitektur
82
bool Cancel
Wenn diese boolesche Property den
Wert True erhält, dann wird der
komplette
Synchronisationsvorgang
abgebrochen.
Mit Hilfe der Properties der Klasse ConflictEventArgs kann in der AnwendungsLogik entschieden werden, ob die SourceEntity importiert wird, oder nicht. Falls die
Entität aus der Quell-Replica importiert werden soll, muss die Property
ImportSourceEntity den Wert True bekommen, anderenfalls bleibt die Entität aus der
Ziel-Replica erhalten. Wenn die Property Cancel den Wert True erhält, dann wird
der
komplette
Synchronisationsvorgang
abgebrochen
und
eine
ImportCancelledException geworfen.
Folgende Abbildung 31 zeigt ein Sequenzdiagramm, welches einen typischen
Importvorgang abbildet. Die Abbildung wird aus Gründen der Übersichtlichkeit im
Querformat dargestellt.
Softwarearchitektur
Abbildung 31: Sequenzdiagramm zum Visualisieren des Importvorgangs (Querformat)
83
Softwarearchitektur
17.4.4
84
Datenbank-Konfliktbehandlungen
Um die Konsistenz der Datenbank zu gewährleisten werden häufig Fremdschlüssel
verwendet.
Dadurch
entstehen
allerdings
Abhängigkeiten
der
Tabellen
untereinander, wodurch manipulative Operationen wie Einfügen, Bearbeiten und
Löschen von Datensätzen ohne entsprechende Behandlung häufig nicht durchgeführt
werden
können.
Eine
naheliegende
Lösung
dieses
Problems
wäre
die
vorübergehende Deaktivierung der Fremdschlüssel während der Transaktion. Dies
führt unter Microsoft SQL Server 2008 allerdings zum vollständigen Sperren von
allen Tabellen, auf welche sich die Fremdschlüssel beziehen. Um dieses Verfahren
bei ThemiSync anzuwenden, muss
allerdings der Entwickler selbst die
Fremdschlüssel aushängen und ThemiSync dabei die Transaktion mitliefern.
Ein einfaches Beispiel für das Deaktivieren der Fremdschlüssel gibt folgender CodeAusschnitt:
String path = "";
ThemiSyncImport themiSyncImport = null;
Database dbSession =
DatabaseManager.Instance.Database.BeginTransaction();
try
{
// disable the foreign key
// FK_Trainer_ChefTrainer
dbSession.ExecuteNonQuery("ALTER TABLE Trainer NOCHECK
CONSTRAINT FK_Trainer_ChefTrainer");
themiSyncImport = new ThemiSyncImport(dbSession, path);
themiSyncImport.Start();
// enable the foreign key
// FK_Trainer_ChefTrainer
dbSession.ExecuteNonQuery("ALTER TABLE Trainer CHECK
CONSTRAINT FK_Trainer_ChefTrainer");
dbSession.CommitTransaction();
}
catch
{
dbSession.RollBackTransaction();
throw;
}
In diesem Code-Ausschnitt wird ein Datenbank-Archiv, dessen Pfad in der StringVariable path steht, importiert. Dabei handelt es sich um eine rekursive Struktur,
welche Daten von Trainern beinhalten. Die rekursive Struktur entsteht dadurch, dass
Softwarearchitektur
85
manche Trainer eine übergeordnete Rolle spielen und dabei Chef-Trainer von
anderen Trainern sind. Dies wurde mit einem rekursiven Verweis auf dieselbe
Tabelle, namens Trainer realisiert
Damit nun keine Konflikte während des Import-Vorganges auftreten, wird vor dem
Import-Vorgang mit der Methode dbSession.ExecuteNonQuery() das ALTER TABLE
SQL-Statement mit der Option NOCHECK CONSTRAINT ausgeführt, um den
genannten Fremdschlüssel zu deaktivieren. Nach dem Importieren wird dieser analog
dazu mit der Option CHECK CONSTRAINT allerdings wieder aktiviert.
Da bei der vorher genannten Technik die Nebenläufigkeit allerdings stark
eingeschränkt werden kann, haben wir uns für eine weitere Lösung entschieden.
Unsere Lösung besteht aus zwei Kernbereichen:
1. Die unterschiedlichen Entitäts-Typen werden in einer vorgegebenen
Reihenfolge importiert.
2. Durch spezielle Ereignisse kann der Entwickler vor und nach dem
Importvorgang Entitäten bearbeiten, sodass Konflikte vermieden werden
können.
Ad 1
Standardmäßig wird eine Import-Reihenfolge gewählt, welche automatisch von
ThemiSync mit einem Algorithmus (siehe 15.3.2) berechnet wurde, sodass möglichst
keine Konflikte beim Importieren auftreten. Zusätzlich besteht aber auch die
Möglichkeit die Reihenfolge temporär selber zu beeinflussen. Dies ermöglicht die
Property ImportConfigurationEntityComparer der Klasse ThemiSyncImport, mit
welcher eine benutzerdefinierte Vergleichsmethode hinterlegt werden kann, die das
IComparer Interface implementiert.
Ad 2
Die Klasse ThemiSyncImport ermöglicht anhand von unterschiedlichen Ereignissen
das Vermeiden von Konflikten, welche einen Import-Vorgang unmöglich machen
würden. Dafür stehen folgende Ereignisse zur Verfügung:
1. BeforeDelete
2. PreImport
3. PostImport
Softwarearchitektur
Event-Handler
86
für
das
Ereignis
BeforeDelete
können
dabei
direkt
in
ThemiSyncImport registriert werden und gelten übergreifend für alle Entitäts-Typen
und Konfigurations-Gruppen.
Die Ereignisse PreImport und PostImport müssen für jeden betreffenden EntitätsTyp unabhängig registriert werden. Das ermöglichen folgende Methoden indem sie
eine Instanz der Klasse ImportHandler passend zum übergebenen Entitäts-Typ
zurückliefern.
public ImportHandler GetImportHandler(short entityTypeID)
public ImportHandler GetImportHandler(EntityTypeEntity entityType)
Die Klasse ImportHandler bietet dann die Properties PreImport und PostImport an,
wodurch individuelle Event-Handler registriert werden können.
Im Folgenden werden nun die einzelnen Ereignisse im Detail betrachtet.
BeforeDelete
Durch das Ereignis BeforeDelete können vor dem Löschen einer Entität, Verweise
auf diese ebenfalls gelöscht werden, damit der Löschvorgang fehlerfrei durchgeführt
werden kann. Eine Instanz der Klasse BeforeDeleteEventArgs wird beim Auslösen
des BeforeDelete Ereignisses mit gesendet, welche folgende Properties besitzt:
List<AbstractBusinessObject>
Entities
Die Liste aller Entitäten, die in der
ganzen Konfigurationsgruppe gelöscht
werden.
bool Cancel
Wenn diese boolesche Property den
Wert True erhält, dann wird der
komplette
Synchronisationsvorgang
abgebrochen.
Wenn das Flag Cancel den Wert True erhält, dann wird der Importvorgang
abgebrochen und eine ImportCancelledException geworfen.
Softwarearchitektur
87
PreImport
Dieses Ereignis tritt kurz vor dem Importieren einer Entität auf, die ThemiSync für
das Importieren gekennzeichnet hat. Dem Ereignis wird eine Instanz der Klasse
PreImportEventArgs mit gesendet, welche folgende Properties besitzt:
AbstractBusinessObject Entity
Die Entität, welche gerade importiert
werden sollte.
bool IsIncludedInPostImportEvent
Wenn diese boolesche Property auf
den Wert True gesetzt wird, dann wird
die Entität, welche gerade importiert
werden sollte, für das PostImport
Ereignis
vorgemerkt
und
dessen
Entitäts-Liste eingereiht.
Mit diesem Ereignis werden üblicherweise Verweise, welche während des ImportVorgangs zu Problemen führen, temporär gelöscht. Durch das Setzen des Flags
IsIncludedInPostImportEvent auf True wird die Entität später beim Ereignis
PostImport mit gesendet, wodurch der Verweis wieder neu gesetzt werden kann.
PostImport
Nachdem alle Entitäten importiert oder behandelt wurden, wird das PostImport
Ereignis per Konfigurationsgruppe einmalig ausgeführt. Dabei werden alle Entitäten
der Konfigurationsgruppe, welche zuvor im PreImport Ereignis anhand des Flags
IsIncludedInPostImportEvent
markiert
wurden,
mitgeführt,
sodass
diese
nachbehandelt werden können. Eine Instanz der Klasse PostImportEventArgs liefert
dabei diese Entitäten als Liste in folgender Form:
List<AbstractBusinessObject>
Entities
Die Liste aller Entitäten, die in der
ganzen Konfigurationsgruppe während
des PreImport Ereignisses für die
Nachbehandlung vorgemerkt wurden.
Softwarearchitektur
88
Üblicherweise werden die Verweise, welche während des PreImport Ereignisses
gelöscht wurden, in diesem Ereignis wieder neu gesetzt, sodass die Entitäten ihren
vorherigen Zustand zurück erhalten.
Mit folgendem Code-Ausschnitt wird nun wieder dieselbe Problemstellung, wie im
vorherigen
Code-Ausschnitt
behandelt.
Dabei
handelt
es
sich
um
das
Synchronisieren von Trainer-Daten, welche zusätzliche eine rekursive Struktur
besitzen. Die Rekursion ergibt sich daraus, dass die Tabelle Trainer eine Spalte
ChefTrainer besitzt, um die Trainerstruktur hierarchisch abbilden zu können.
Softwarearchitektur
89
String path = "";
Database dbSession =
DatabaseManager.Instance.Database.BeginTransaction();
ThemiSyncImport themiSyncImport = null;
Dictionary<Guid, Guid> chefTrainerDictionary =
new Dictionary<Guid, Guid>();
try
{
themiSyncImport = new ThemiSyncImport(dbSession, path);
ImportHandler importHandlerTrainer =
themiSyncImport.GetImportHandler(
EntityTypeDAC.Instance.GetEntityType(
TrainerDAC.Instance.BusinessObjectType
)
);
importHandlerTrainer.PreImport +=
new EventHandler<PreImportEventArgs>(
delegate(object o, PreImportEventArgs e)
{
TrainerEntity entity = e.Entity as TrainerEntity;
if (entity.ChefTrainerObj != null)
{
chefTrainerDictionary.Add(entity.TrainerID,
entity.ChefTrainerID);
entity.ChefTrainerObj = null;
e.IsIncludedInPostImportEvent = true;
}
}
);
importHandlerTrainer.PostImport +=
new EventHandler<PostImportEventArgs>(
delegate(object o, PostImportEventArgs e)
{
foreach (AbstractBusinessObject abstractObject in
e.Entities)
{
TrainerEntity entity =
abstractObject as TrainerEntity;
entity.ChefTrainerID =
chefTrainerDictionary[entity.TrainerID];
}
}
);
themiSyncImport.Start();
dbSession.CommitTransaction();
}
catch
{
dbSession.RollBackTransaction();
throw;
}
Die Variable path verweist auf den Export-Container, der bereits exportierten Daten.
Die Methode GetImportHandler, welche die ThemiSyncImport Instanz anbietet,
Softwarearchitektur
90
liefert den ImportHandler, der für die Trainer-Entitäten zuständig ist zurück. An
diesem ImportHandler werden nun Behandlungen für die Ereignisse PreImport und
PostImport registriert. Dabei werden anonyme Methoden verwendet, da die
Behandlungen nur für genau diese Ereignisse verwendet werden.
Im PreImport Ereignis wird überprüft, ob die mitgelieferte Entität einen Verweis auf
den Chef-Trainer besitzt. Falls dies nicht der Fall ist, dann wird die Behandlung
beendet und die Entität ohne Änderung importiert. Falls die Entität allerdings einen
solchen Verweis besitzt, dann wird der Verweis zwischengespeichert und in der
Entität entfernt. Das Flag IsIncludedInPostImportEvent wird auf True gesetzt, damit
die Entität im PostImport Ereignis wieder mitgeliefert wird, sodass die Änderung
wieder rückgängig gemacht werden kann.
Im PostImport Ereignis werden alle vorgemerkten Entitäten als Liste mitgeliefert
und durchlaufen. Dabei werden alle vorher entfernten Verweise auf die Chef-Trainer
wieder hergestellt.
Qualitätssicherung
Das Hauptziel dieses Projektes war es, eine Synchronisationsmöglichkeit für diverse
Daten der Software TrainingStudio innerhalb beliebig vieler Instanzen synchron zu
halten. Wie bereits in vorhergehenden Kapiteln beschrieben wurde, ist die
Vorgängerversion auf dem Markt bereits gut vertreten und die neue Version, welche
die Vorgängerversion ablösen soll, soll noch mehr Klientel anwerben. Das bedeutet,
dass
das
TrainingStudio
zusammen
mit
ThemiSync
keine
„langsame
Einführungsphase“ erleben wird, sondern bereits von Anfang an für alle
TrainingStudio–Kunden der Firma InfPro fehlerfrei funktionieren muss.
Neben allgemeinen Gründen für ein gutes Qualitätsmanagement bei der
Softwareentwicklung, fordert dieser Umstand diesbezüglich besondere Sorgfalt.
Qualitätssicherung wurde während des gesamten Projektverlaufs besonders
fokussiert.
Folgende Grafik (Abbildung 32) gibt einen Überblick über die relevanten
Softwareentwicklungsphasen und den eingesetzten qualitätssicherungsspezifischen
Merkmalen, welche in folgenden Kapiteln detailliert beschrieben werden.
Qualitätssicherung
92
Analyse
Entwurf
Implementierung
Anforderungstest
Integration
Designtest
Einsatz
Funktionstest
Wartung
Systemtest
Abbildung 32: Projektphasen Qualitätsmanagement
18
Analyse
Die Qualitätssicherung beginnt bereits in der Planungsphase eines Projektes. Dabei
gilt es die Anforderungen auszuarbeiten und in Zusammenarbeit mit dem
Auftraggeber exakt und testfähig zu formulieren.
Nach dem
Erhalt
des
Pflichtenheftes
und
der klaren
Abgrenzung des
Aufgabenbereichs wurde vor Konzeptionsbeginn in mehreren Sitzungen mit dem
Auftraggeber überprüft, ob beiderseits (Auftraggeber, Auftragnehmer) alles richtig
und sinngemäß übereinstimmend verstanden wurde. Dabei standen neben
Funktionsvollständigkeit,
Beschreibungsvollständigkeit,
Begriffseindeutigkeit,
Widersprüche in Anforderungen, und anderen wichtigen Merkmalen der
Anforderungsdefinition auch firmeninterne Konventionen bezüglich Sourcecode,
Tabellenbezeichnungen
und
allgemeine
Usancen
zur
Debatte.
Um
die
Funktionsvollständigkeit wurden verschiedene Szenarien der Anwendungsfälle
(siehe 12) detailliert durch besprochen und effektuiert.
19
Entwurf
Bei der Entwurfsphase ging es hinsichtlich Qualitätssicherung vor allem darum, die
Abläufe, Schnittstellen und Funktionalitäten im Detail abzuklären. Hier wurden die
verwendeten Techniken fixiert und anhand diverser Beispielimplementierungen
überprüft/getestet, ob sie für den benötigten Einsatz geeignet sind. Auch hier wurde
zusätzlich im Rahmen von Besprechungen und Progress Reviews vom Auftraggeber
zur Qualitätssicherung beigetragen.
Qualitätssicherung
20
93
Implementierung
Die Entwicklungsphase der Implementierung benötigt ein besonders großes Maß an
Qualitätsmanagement, da besonders hier viele Fehler passieren können. Folgende
Werkzeuge und Techniken trugen während der Umsetzung des Projektes zur
Qualitätssicherung bei.
20.1
Extreme Programming (XP)
Der Softwareentwicklungsprozess von ThemiSync lief in vielen Aspekten nach dem
agilen Ansatz des Extreme Programmings ab. Kurz beschrieben handelt es sich dabei
um eine Technik, welche es für kleine Teams ermöglicht, langlebige Software zu
erstellen und auf vage und sich rasch ändernde Anforderungen reagieren zu können.
Konkret kamen folgende XP-Elemente zum Einsatz:
Kurze Iterationen
In mehr oder weniger regelmäßigen und relativ engen Zeitabständen wurden
Sitzungen mit dem Auftraggeber abgehalten und dabei zum Einen der aktuelle Stand
präsentiert, sowie Codereviews vom Auftraggber durchgeführt (siehe 20.2) und zum
Anderen die weiteren Schritte bis zum nächsten Meeting fixiert.
Offene Kommunikation im Team
Unerlässlich beim Extreme Programming ist die offene Kommunikation im Team.
Sofern gemeinsam programmiert wurde (siehe 20.3) war dieses Kriterium ohnehin
leicht realisierbar, aber auch andernfalls war das Projektteam ständig in Kontakt und
über den Projektstand detailliert informiert.
Refactoring
Jeder im Projektteam fühlt sich für die Qualität von ThemiSync verantwortlich.
Deshalb wurde das System während der Implementierungsphase ständig durch
refactorings
optimiert.
Dabei
spielte
es
keine
Rolle
von
wem
der
optimierungswürdige Code stammte – es ging darum die Qualität zu erhöhen.
Fortlaufende Integration
ThemiSync wurde bereits in einer sehr frühen Projektphase partiell in das
TrainingStudio integriert. Damit lief es von Beginn an mit dem automatisierten
Qualitätssicherung
94
Testverfahren über Unittests (siehe 20.4) und Cruisecontrol (siehe 20.5) mit und
stand unter permanenter Kontrolle.
20.2
Codereviews
Kritische Codeteile wurden regelmäßig von unserem Auftraggeber durchgesehen
und mit Verbesserungsvorschlägen kommentiert. Da unser Auftraggeber und
technischer Betreuer – Herr Dipl.-Ing. Hansjörg Haller – ein sehr renommierter und
erfahrener Softwareentwickler ist, stellen die zahlreichen Tipps, Vorschläge und
Hinweise
auf
Gefahrenquellen
einen
sehr
wichtigen
Bestandteil
der
Qualitätssicherung von ThemiSync dar.
20.3
Pair-Programming
Wo immer es dem Projektteam möglich war und sinnvoll erschien, wurde
gemeinsam an einem Computer entwickelt. Pair-Programming bringt einige Vorteile
mit sich. Unter Anderem zählen dazu:
20.4
-
Höhere Disziplin (Pausen, vereinbarte Konventionen, …)
-
Besserer Code (durch permanente gegenseitige Kontrolle)
-
Motivationsfördernd (Im Team machts mehr Spaß als allein)
-
Mentoring (Wissen wird verteilt)
-
…
Unittests
Parallel zur aktuellen Iteration wurden Unittests geschrieben, um die Funktionalität
zu automatisieren, sowie dauerhaft und regelmäßig überprüfen zu können. Hierbei
kam das Framework NUnit zum Einsatz, welches bei allen Projekten der Firma
InfPro verwendet wird. Dadurch wurde auch die Integration in Cruisecontrol (siehe
20.5) ermöglicht.
20.5
Cruisecontrol
Cruisecontrol ist ein Java-basiertes System, welches dazu dient während eines
Softwareentwicklungsprozesses kontinuierliche Erstellungsprozesse automatisiert
anzustoßen. Dadurch werden neue Softwareelemente bei jedem Check in das
Qualitätssicherung
95
gesamte System integriert und das Zusammenspiel der Komponenten über Unittests
automatisch getestet.
Dieses Werkzeug wird von der Firma InfPro eingesetzt und uns von Beginn an zur
Verfügung gestellt. Bereits die Tatsache, dass jeder Entwickler der Firma sofort über
einen fehlerhaften Build informiert wird sorgt dafür, dass man sehr genau auf die
Richtigkeit seines Codes achtet.
21
Integration
Da
ThemiSync,
wie
bereits
erwähnt
kontinuierlich
in
das
Zielsystem
(TrainingStudio) integriert wurde und das Gesamte dadurch einer ständigen
Qualitätskontrolle unterlag, waren bei der finalen Integration keine zusätzlichen
qualitätssicherungsfördernden Maßnahmen nötig.
22
Einsatz & Wartung
Die Qualitätssicherung während des Einsatzes und der Wartung von ThemiSync liegt
bei der Firma InfPro. Im Rahmen des Projektes wird die Software in das
firmeninterne Unittesting-System integriert und somit automatisiert getestet.
Benutzerhandbuch
23
Einleitung
Dieses Benutzerhandbuch dient als Hilfestellung und Nachschlagewerk für
Entwickler, welche ThemiSync zur Datensynchronisation verwenden möchten. Es
beschreibt anhand eines einfachen Beispiels, welches auf einer bereits bestehenden
IBOF-Applikation aufbaut, wie die Synchronisations-API eingesetzt werden kann.
Dabei wird auf alle nötigen Vorbereitungsarbeiten, Konfigurationsmöglichkeiten und
den Umgang mit den Schnittstellen detailliert eingegangen.
24
24.1
Beispielapplikation
Einleitung
Die Beispielapplikation ist sehr einfach gehalten und besteht aus nur vier Klassen.
Trotzdem bietet sie die Möglichkeit, alle Standard- und Spezialfälle bezüglich
ThemiSync zu erklären. Als zugrundeliegendes Datenbanksystem wird Microsoft
SQL Server 2008 eingesetzt, während für Export- und Importdaten Microsoft SQL
CE verwendet wird.
Folgendes UML Diagramm in Abbildung 33 zeigt die Grundstruktur der
Geschäftslogik:
Benutzerhandbuch
98
Abbildung 33: Beispielapplikation UML Diagramm
24.2
Benötigte DLLs
Um ThemiSync in der Beispielapplikation verwenden zu können, müssen folgende
DLLs referenziert werden:
-
InfPro.ThemiSync.BusinessObjects.dll
-
InfPro.ThemiSync.dll
-
InfPro.ThemiSync.Exceptions.dll
-
InfPro.ThemiSync.Synchronization.dll
-
InfPro.ThemiSync.Utils.dll
-
NVelocity.dll
-
ICSharpCode.SharpZipLib.dll
-
InfPro.Databases.SQLServerCEDriver.dll (Transportdatenbank)
Benutzerhandbuch
25
99
ThemiSync Konfigurationstool
Für eine einfache Installation und Konfiguration von ThemiSync-erweiterten IBOF
Projekten, steht ein Tool zur Verfügung. Abbildung 34 zeigt einen Screenshot des
Tools. Das ThemiSync-Configurationtool erhält alle benötigten Informationen
(Connectionstrings, Username, Passwort, …) über die IBOF-Konfigurationsdatei
(.boc) welche für jedes IBOF Projekt ohnehin erstellt werden muss. Bevor die
Konfigurationsdatei gewählt wurde, ist keine Aktion möglich. Die einzelnen
Features des ThemiSync-Configurationtools werden wie folgt in den entsprechenden
Abschnitten detailliert beschrieben.
Benutzerhandbuch
100
Abbildung 34: ThemiSync Configurationtool
26
26.1
Vorbereitungen (Datenbank, IBOF)
Datenbank
Die Datenbank eines IBOF-Projektes welches mit ThemiSync erweitert werden soll,
muss für das Persistieren der benötigten Metadaten und zur Verwaltung diverser
Konfigurationsdaten einige Tabellen bereitstellen.
Für eine bessere Übersichtlichkeit im Datenbankmodell bietet sich der Einsatz von
Schemata an. Alle ThemiSync-Tabellen müssen sich im Schema „ThemiSync“
befinden.
Benutzerhandbuch
101
Folgendes Datenbankmodell in Abbildung 35 zeigt die zwingend zu verwendende
Tabellenstruktur, welche zusätzlich zu denen von der Applikation verwendeten
Tabellen in der Anwendungsdatenbank erstellt werden muss.
Abbildung 35: ThemiSync Datenbanktabellen Übersicht
Benutzerhandbuch
102
Die Konfigurationstabellen „ImportRule“, „PreImportAction“ und „SystemInfo“
müssen mit folgenden Zeilen befüllt sein:
ImportRule
ImportRuleID
Name
0
Overwrite
1
KeepExisting
2
ApplicationDefined
PreImportAction
PreImportActionID Name
0
Nothing
1
Delete
SystemInfo
SystemInfoID
Name
Value
Guid.NewGuid()
ThemiSyncVersion
Aktuelle
Versionsnummer
ThemiSync
von
Guid.NewGuid()
DatabaseVersion
Aktuelle
Versionsnummer des
Datenbankschemas
Guid.NewGuid()
ReplicaID
Eindeutige ID der
Datenbank (Guid)
Tipp: Alle benötigten Tabellen und Datensätze (ausgenommen die Daten der Tabelle
SystemInfo) können automatisiert über das Konfigurationstool erstellt werden.
Öffnen Sie dazu das Tool und wählen unter dem Reiter „Common“ (im Bereich
„Database“) das entsprechende Skript aus (im Normalfall wird es die aktuellste
Benutzerhandbuch
103
Version sein). Anschließend klicken Sie auf „execute“ – eine Messagebox informiert
Sie über den Verlauf der Installation.
26.1.1
Beispielsapplikation
Nach erfolgreicher Erweiterung der Beispielapplikationsdatenbank enthält die
Datenbank neben dem Schema „ThemiSync“ folgende Tabellen, die in Abbildung 36
illustriert werden:
Abbildung 36: Beispielapplikation Tabellen
26.2
IBOF
Für den Einsatz von ThemiSync wurde der IBOF-Generator um einige Einstellungen
erweitert. Neben den Standardeinstellungen muss für ThemiSync-erweiterte IBOFProjekte auf Einstellungen geachtet werden, die in folgender Abbildung 37 mit roten
Ellipsen gekennzeichnet sind:
Benutzerhandbuch
104
Abbildung 37: IBOF Generator
26.2.1
Is Used For Sync (1)
Dieses Flag entscheidet global auf Typ-Ebene ob die entsprechenden Daten
synchronisiert werden sollen, oder nicht. Bei Hierarchien ist darauf zu achten, dass
nur der betreffende Typ markiert werden muss, nicht aber die darunter liegenden
generalisierten Klassen (Siehe 26.2.3).
26.2.2
Is used for SyncHash (2)
Über dieses Flag können einzelne Spaltenwerte (Properties) von der Generierung des
Vergleichs-Hashs (SyncHash) ausgenommen werden. Änderungen an abgewählten
Properties werden bei der Synchronisation ignoriert. Damit ist es zum Beispiel
möglich die letzte Speicherung zeitlich zu protokollieren aber nur im Falle einer
tatsächlichen Wertänderung in einem anderen Datenfeld zu synchronisieren.
26.2.3
Beispielapplikation – IBOF Konfiguration
Im Beispiel wird davon ausgegangen, dass alle Klassen synchronisierbar gemacht
werden müssen. Es wird daher überall das Flag „Is Used for Sync“ markiert. Da es
Applikationsseitig auch User ohne weitere Ausprägung gibt wird dieses auch für den
Typ User gesetzt. Wäre dies nicht der Fall, gäbe es nur User-Instanzen von den
Typen Athlet und Trainer, müsste man den Typ User von der Synchronisation
Benutzerhandbuch
105
ausnehmen, da ThemiSync die Daten auf Typ-Ebene und nicht auf Tabellen-Ebene
verwendet.
Das Datenfeld ChangedDateTime existiert durch die Klassenhierarchie in allen
Typen des Beispiels, und wird Applikationsseitig immer dann aktualisiert, wenn eine
Instanz des entsprechenden Typs gespeichert wird – unabhängig davon, ob sich
andere Werte tatsächlich geändert haben oder nicht. Diese Property ist also nie
entscheidend dafür, ob sich der (applikationsrelevante) Objektzustand geändert hat
und sollte daher bei der Synchhash-Generierung außer Acht gelassen werden. Dies
wird durch Deaktivierung des Flags „Is used for SyncHash“ bei den entsprechenden
Feldern markiert.
Die abgeschlossene IBOF Konfiguration unserer Beispielapplikation sieht also
folgendermaßen aus:
Is used for Sync
Is used for SyncHash

Athlet
AthletID

AthleteGroupID

Weight

AthleteGroup

AthleteGroupID

TrainerID

Name

ChangedDateTime


Trainer
TrainerID

Benutzerhandbuch
106
BossTrainerID

SportsClub


User
27
UserID

FirstName

LastName

Birthdate

ChangedDateTime

Konfiguration (ThemiSync)
Die
Konfiguration
beziehungsweise
von
ThemiSync
besteht
Importkonfigurationen,
grundsätzlich
aus
Export-
Konfigurationsgruppen
und
Konfigurationsgruppen-Zuordnungen. Alle erforderlichen Konfigurationseinträge
können bequem über das ThemiSync Konfigurationstool verwaltet werden.
Folgendes
Datenmodell
Konfigurationsstruktur:
(Abbildung
38)
zeigt
den
Aufbau
der
Benutzerhandbuch
107
Abbildung 38: Datenmodell ThemiSync Konfiguration
27.1
Exportkonfiguration (ExportConfigurationEntity)
Eine Instanz des Typs ExportConfigurationEntity stellt eine atomare Einheit eines
Exportvorgangs dar. Sie ist genau einem Entitätstyp zugeordnet (siehe 27.5) und
muss einer Konfigurationsgruppe (siehe 27.3) angehören.
Folgende Auflistung erklärt die Bedeutung der einzustellenden Parameter einer
Exportkonfiguration:
Property
Entity Type (Entitätstyp)
Beschreibung
Die Zuweisung des Entitätstyps entscheidet für welche
Klasse die Konfiguration bestimmt ist. ThemiSyncintern erfolgt damit die eindeutige Zuordnung von
Einträgen
des
Änderungs-
beziehungsweise
Löschungsprotokolls an einen Applikationsdatentyp.
Weiters
bestimmt
der
Abarbeitungsreihenfolge
Entitätstyp
beim
über
Einfügen
die
der
Synchronisationsdaten in die Datenbank.
use Tombstone
Für eine vollständige Synchronisation muss dieses Flag
aktiv
sein,
Informationen
da
im
deaktivierten
Zustand
keine
über
protokollierte
Löschvorgänge
exportiert werden und somit auf der Empfängerseite alle
Daten erhalten bleiben. Bei Einwegsynchronisationen
kann es durchaus sinnvoll sein „use Tombstone“ auf
Benutzerhandbuch
108
False zu setzen.
Config Group
Eindeutige Zuordnung zu einer Konfigurationsgruppe
(siehe 27.3)
Description
Bietet
Platz
für
eine
Beschreibung
der
Exportkonfiguration (für die Synchronisation nicht
relevant)
Join Statement
Dieser optionale Parameter ermöglicht das Joinen von
Datenbanktabellen für die Export-Datenselektion. Er
beinhaltet SQL-Code und bietet die Möglichkeit zur
Verwendung von NVelocity-Variablen an (siehe 27.6).
Dabei ist zu beachten, dass auf alle Datenbanktabellen
einer
Klassenhierarchie
Statement
zugegriffen
ohne
zusätzliches
werden
kann.
JoinWeitere
Informationen dazu entnehmen Sie bitte der IBOFDokumentation (IFinder)
Where Clause
Mit der Where Clause ist es möglich, die zu
exportierenden Daten einzuschränken, wobei auf alle
Tabellen
der
zur
Klasse
gehörenden,
deren
generalisierten Klassen-Tabellen und den zusätzlich
gejointen Datenbanktabellen zugegriffen werden kann.
Der Parameter enthält SQL-Code und bietet die
Möglichkeit zur Verwendung von NVelocity-Variablen
an (siehe 27.6). Weitere Informationen dazu entnehmen
Sie bitte der IBOF-Dokumentation (IFinder)
27.2
Importkonfiguration (ImportConfigurationEntity)
Instanzen des Typs ImportConfigurationEntity stellen atomare Einheiten eines
Importvorgangs dar. Sie sind genau einem Entitätstyp zugeordnet (siehe 27.5) und
müssen einer Konfigurationsgruppe (siehe 27.3) angehören.
Benutzerhandbuch
109
Folgende Auflistung erklärt die Bedeutung der einzustellenden Parameter einer
Importkonfiguration:
Property
Beschreibung
Entity Type (Entitätstyp)
siehe 27.1
use Tombstone
siehe 27.1
Config Group
siehe 27.1
Description
siehe 27.1
Preimport Rule
Dieser Parameter entscheidet darüber, was vor dem
Importieren mit den zum Entitätstyp passenden Daten
passieren soll (betrifft die gesamte Tabelle)
Optionen:
Import Rule
-
Nothing: keine Aktion
-
Delete: alle Daten der Tabelle werden gelöscht
Dieser
Parameter
entscheidet
darüber,
wie
mit
Konflikten verfahren wird.
Optionen:
-
Overwrite:
Die
Daten
der
Empfängerseite
werden
überschrieben.
-
KeepExisting:
Die Daten der Empfängerseite bleiben bestehen.
-
ApplicationDefined:
Die Entscheidung ob die Daten überschrieben
werden oder erhalten bleiben, liegt an der
Applikation.
Join Statement
siehe 27.1
Benutzerhandbuch
110
Where Clause
27.3
siehe 27.1
Konfigurationsgruppe (ConfigurationGroupEntity)
In einer Konfigurationsgruppe können mehrere Konfigurationen zusammengefasst
werden. Aus jeder Konfigurationsgruppe entsteht beim Exportvorgang eine
Transportdatenbank,
welche
alle
selektierten
Daten
aller
enthaltenen
Konfigurationen enthält. Beim Importvorgang entscheiden die Einträge in der
ConfigurationGroupMapping-Tabelle,
(siehe
27.5)
welche
Importkonfigurationen/Transportdatenbanken importiert werden sollen.
27.4
Konfigurationsgruppen-Zuordnung (ConfigurationGroupMappingEntity)
Die Konfigurationsgruppen-Zuordnung greift beim Importieren und entscheidet
darüber, welche Exportkonfigurationsgruppen zu einer Importkonfigurationsgruppe
gehören.
So
könnte
zum
„ImportPersonsConfigGroup“
Beispiel
für
die
die
Importkonfigurationsgruppe
Exportkonfigurationsgruppen
„ExportAthleteConfigGroup“ und „ExportTrainerConfigGroup“ verwendet werden.
27.5
Entitätstyp (EntityTypeEntity)
Ein Entitätstyp ist die Darstellung von Applikationsklassen in Form von
Objektinstanzen der Klasse EntityTypeEntity. Entitätstypen bieten ThemiSync die
Möglichkeit einfach auf diverse Klasseninformationen (Name, Namespace)
zugreifen zu können und entscheidet beim Importvorgang über die Property
ResolutionSequenceNumber in welcher Reihenfolge die Importkonfigurationen
abgearbeitet werden. Diese eindeutige Reihenfolge ist nötig, um beim Einfügen der
Daten Konflikte mit Foreign Key Constraints in der Datenbank zu vermeiden.
Die statischen Methode
ThemiSyncConfig.Initialize(Database, List<IBusinessObjectDAC>)
erstellt fehlende Entitätstypen und berechnet deren Sequenznummer automatisch,
falls der Eintrag „CleanEntityTypes“ in der Tabelle SystemInfo mit „True“ belegt ist.
Gibt es also Änderungen an der Datenstruktur einer bereits konfigurierten
Benutzerhandbuch
111
ThemiSync-erweiterten Applikation, so muss dieser Eintrag der SystemInfo-Tabelle
einmalig manuell auf „True“ (string) gesetzt werden.
27.6
Beispielapplikation – ThemiSync Konfiguration
Als praktisches Beispiel werden nun die ThemiSync Konfigurationen zweier
Synchronisationsszenarien detailliert beschrieben.
Bevor nun Export- oder Importkonfigurationen angelegt werden können, muss dafür
gesorgt werden, dass die Tabelle EntityType befüllt ist. Dafür wird in der
Beispielapplikation (nachdem das IBOF-DB-Environment initialisiert wurde) die
statische Methode
ThemiSyncConfig.Initialize(Database, List<IBusinessObjectDAC>)
mit folgenden Parameterwerten aufgerufen:
GlobalDBEnvironment.Instance.Database,
DatabaseManager.Instance.GetAllRegisteredDACClasses()
Danach befindet sich für jede der vier Klassen ein Eintrag in der Tabelle und es kann
mit der Erstellung der Konfigurationseinträge begonnen werden.
27.6.1
Szenario 1
Beschreibung: Im Szenario 1 sollen alle Personen (Trainer, Athleten, Benutzer) der
Applikation synchronisiert werden.
Konfigurationsgruppen
Für die vollständige Synchronisation aller Personen würden grundsätzlich zwei
Konfigurationsgruppen ausreichen. Um aber flexibel zu bleiben, werden wir für
TrainerEntity,
AhtleteEntity
Konfigurationsgruppe
und
erstellen,
Synchronisationsszenarien
Folgende
vier
welche
TrainerExportConfigGroup
dann
jeweils
werden
eine
separat
verwendet
Konfigurationsgruppen
Configurationtool erstellt:
-
UserEntity
eigene
auch
werden
also
über
für
Exportandere
können.
das
ThemiSync
Benutzerhandbuch
112
-
AthleteExportConfigGroup
-
UserExportConifgGroup
-
PersonsImportConfigGroup
Konfigurationsgruppen-Zuweisungen
Da beim Importieren alle drei Exportkonfigurationsgruppen verwendet werden
sollen, werden nun drei Configuration Group Mapping – Einträge erstellt:
-
TrainerExportConfigGroup

PersonsImportConfigGroup
-
AthleteExportConfigGroup

PersonsImportConfigGroup
-
UserExportConifgGroup

PersonsImportConfigGroup
Exportkonfigurationen
Da jede Exportkonfigurationsgruppe nur eine Klasse betrifft, befindet sich auch nur
eine Exportkonfiguration darin.
Folgende Tabellen zeigen die benötigen Konfigurationen für das Szenario 1:
TrainerEntity
Entity Type
TrainerEntity
Die zu exportierende Klasse.
use Tobstone
True
Gelöschte Einträge sollen bei der
Synchronisation
berücksichtigt
werden.
Config Group
TrainerExportConfigGroup
Konfigurationsgruppe.
Description
Export aller Trainer
Beliebiger Beschreibungstext.
Join Statement
Es wird keine weitere Tabelle
(außer
Trainer
und
User)
benötigt, deshalb kann dieser
Benutzerhandbuch
113
Parameter leer bleiben.
Da alle Einträge der Tabelle
Where Clause
Trainer exportiert werden sollen
kann
dieser
Parameter
leer
bleiben.
AthletEntity
Entity Type
AthletEntity
siehe TrainerEntity
use Tobstone
True
siehe TrainerEntity
Config Group
AthleteExportConfigGroup
siehe TrainerEntity
Description
Export aller Athleten
siehe TrainerEntity
Join Statement
siehe TrainerEntity
Where Clause
siehe TrainerEntity
UserEntity
Entity Type
UserEntity
siehe TrainerEntity
use Tobstone
True
siehe TrainerEntity
Config Group
AthleteExportConfigGroup
siehe TrainerEntity
Description
Export aller Athleten
siehe TrainerEntity
Join Statement
Where Clause
siehe TrainerEntity
UserID not in (SELECT Da in der Tabelle User nicht
TrainerID FROM Trainer direkt festgestellt werden kann,
Benutzerhandbuch
114
UNION SELECT AthletID ob es in der Tabelle Trainer
FROM Athlet)
beziehungsweise
Athlet
eine
„Spezialisierung“
dazu
gibt,
müssen
die
entsprechenden
Datensätze
händisch
ausgenommen werden.
Importkonfiguration
Die
Konfigurationsgruppe
„PersonsImportConfigGroup“
soll
auf
alle
Exportkonfigurationen reagieren und enthält deshalb für jeden konfigurierten
EntityType eine Importkonfiguration mit folgenden Werten:
TrainerEntity, AthleteEntity, UserEntity
Entity Type
TrainerEntity,
siehe Export TrainerEntity
AthleteEntity, UserEntity
use Tobstone
True
siehe Export TrainerEntity
Config Group
PersonsImportConfigGroup
siehe Export TrainerEntity
Preimport Rule
Nothing
Keine Aktion auf die gesamte
Tabelle vor dem Importvorgang.
Import Rule
ApplicationDefined
Bei Konflikten entscheidet die
Applikation wer gewinnt.
Description
Import
aller
Trainer, siehe Export TrainerEntity
Athleten, User
Join Statement
siehe Export TrainerEntity
Where Clause
siehe Export TrainerEntity
Damit ist die ThemiSync-Konfiguration für das Szenario 1 abgeschlossen.
Benutzerhandbuch
27.6.2
115
Szenario 2
Beschreibung: Beim Szenario 2 soll der aktuell angemeldete Trainer exportiert
werden. Hier soll der Einsatz von NVelocity für die Datenselektion veranschaulicht
werden.
Annahme: Vor der applikationsseitigen Ausführung der Methode
ThemiSyncExport.Start();
wurde über den Methodenaufruf
themiSyncExport.GlobalVelocityManager.RegisterVelocityVariable(…);
die NVelocity-Variable CurrentTrainer registriert, welche den aktuell am System
angemeldeten Trainer (Typ: TrainerEntity) zurückgibt (siehe 28.1.1).
Konfiguration
Es wird eine Exportkonfigurationsgruppe und eine Exportkonfiguration (für Entität
TrainerEntity) erstellt (siehe Szenario 1).
Das entscheidende Merkmal in diesem Fall findet man in der Property Where Clause
der Exportkonfiguration, welche auf die registrierte NVelocity-Variable zugreifen
kann und somit die SQL Abfrage zur Laufzeit dynamisch erzeugt.
TrainerEntity
28
…
…
Where Clause
TrainerID = $CurrentTrainer.TrainerID
…
…
API-Schnittstellen
Alle Methoden und Properties welche vom Programmierer beim Einsatz von
ThemiSync
verwendet
werden
können,
befinden
sich
im
Namespace
InfPro.ThemiSync. Die Klassenhierarchie dieser Library ist in Abbildung 39
dargestellt.
Benutzerhandbuch
116
Abbildung 39: Datenmodell Infpro.ThemiSync
Nachfolgend werden alle enthaltenen Klassen und deren Funktionalität detailliert
beschrieben.
28.1
ThemiSyncBase
ThemiSyncBase
ist
die
Basisklasse
der
Typen
ThemiSyncExport
und
ThemiSyncImport. Sie muss nie direkt instanziert werden, da sie ihre Properties und
Methoden auch den abgeleiteten Klassen zur Verfügung stellt.
Die Property
public VelocityManager GlobalVelocityManager
liefert den Globalen VelocityManager (siehe VelocityManager28.1.1), welcher das
Konfigurationsgruppen-übergreifende
Registrieren
von
Velocity-Variablen
ermöglicht.
Die Methode
public VelocityManager
GetConfigurationGroupVelocityManager(ConfigurationGroupEntity)
liefert den Konfigurationsgruppen-spezifischen VelocityManager. Dieser erlaubt das
Registrieren von Velocity-Variablen welche beim Synchronisationsvorgang nur der
betreffenden Konfigurationsgruppe zur Verfügung stehen.
28.1.1
VelocityManager
Die
Klasse
VelocityManager
befindet
sich
im
Namespace
InfPro.ThemiSync.Utils.Velocity und bietet die Möglichkeit NVelocity-
Benutzerhandbuch
117
Variablen zu registrieren und Strings unter Verwendung der registrierten Variablen
auszuwerten.
Die Registrierung von NVelocity-Variablen erfolgt über folgende Methode:
public void RegisterVelocityVariable(string velocityName,
VelocityCallback dlgt)
Beim Auswerten über
public string Evaluate(string templateString)
werden
beim
Zugriff
auf
NVelocity-Variablen
(velocityName)
die
entsprechenden Delegate-Methoden (dlgt) ausgeführt.
28.2
ThemiSyncConfig
Die Klasse ThemiSyncConfig bietet die Methode
public static void Initialize (Database database,
List<IBusinessObjectDAC> iBusinessObjectDACLst)
welche bei jedem Applikationsstart einmalig ausgeführt werden muss. Dabei wird
die
aktuelle
Datenbank
(z.B.
GlobalDBEnvironment.Instance.Database) und eine Liste aller DACKlassen
der
ThemiSync-erweiterten
IBOF
Applikation
übergeben
(DatabaseManager.Instance.GetAllRegisteredDACClasses()).
Zur Laufzeit kann über die Property
public static bool IsInitialized
überprüft werden, ob Initialize() bereits ausgeführt wurde.
28.3
ThemiSyncExport
Um einen Exportvorgang umsetzen zu können, muss eine Instanz der Klasse
ThemiSyncExport erstellt werden. Dem Konstruktor dieser Klasse kann eine
SourceDatabase (Database-Instanz) und ein ExportPath (string) übergeben werden.
Die Standardwerte (falls sie dem Konstruktor nicht übergeben werden) dieser
Properties sind:
Benutzerhandbuch
118
ExportPath:
Path.GetTempFileName()+DBArchive.GetArchiveFileExtension()
SourceDatabase:
GlobalDBEnvironment.Instance.Database
Die Property
public List<ConfigurationGroupEntity> ConfigurationGroups
liefert die Liste der zu exportierenden Konfigurationsgruppen (siehe 27.3).
Wird als Transportdatenbank ein File-Basiertes Datenbanksystem verwendet, so
muss der Pfad zur Vorlagedatenbank in der Property
public string TemplateDatabasePath
gespeichert werden. Die Vorlagedatenbank muss exakt dieselbe Datenstruktur
besitzen, wie die Quell-Datenbank und darf keine Foreign Key Contstraints
enthalten.
Die Methode
public void Start()
stößt den Exportvorgang endgültig an.
ThemiSyncExport bietet zur Information über den aktuellen Fortschritt während
eines Exportvorganges das Event
public event EventHandler<ExportProgressChangedEventArgs>
ExportProgressChanged
an.
28.4
ThemiSyncImport
Jeder Importvorgang basiert auf einer Instanz der Klasse ThemiSyncImport. Der
Konstruktor dieser Klasse benötigt mindestens den Pfad zum Transportcontainer und
kann optional auch mit der DestinationDatabase (Database-Instanz) initialisiert
werden. Wird die DestinationDatabase nicht übergeben, so wird standardmäßig
GlobalDBEnvironment.Instance.Database
verwendet.
Benutzerhandbuch
119
Über die Property
public IComparer<ImportConfigurationEntity>
ImportConfigurationEntityComparer
kann die automatisch berechnete Abarbeitungsreihenfolge der Importkonfigurationen
von der Applikation aus geändert werden.
Die überladenen Methoden
public ImportHandler GetImportHandler(EntityTypeEntity entityType)
public ImportHandler GetImportHandler(short entityTypeID)
liefern einen ImportHandler für den übergebenen EntityType. Ein ImportHandler
ermöglicht das Bearbeiten von importierenden Objektinstanzen vor und nach dem
Synchronisationsvorgang. Damit sind sehr viele Spezialfälle – wie zum Beispiel die
Synchronisation von rekursiven Strukturen – realisierbar. Bei einer Rekursion würde
man beispielsweise beim ImportHandler.PreImport-Event die referenzierten
untergeordneten Objekte aushängen, indem man die ID im Foreign Key Feld
entfernt. Diese IDs merkt man sich Applikationsseitig und fügt sie beim
ImportHandler.PostImport-Event wieder ein.
Die Methode
public void Start()
stößt den Importvorgang endgültig an.
Wurde bei einer Importkonfiguration die Import Rule „ApplicationDefined“ gewählt,
so muss für die Applikationsseitige Konfliktbehandlung das Event
public event EventHandler<ConflictEventArgs> Conflict;
implementiert werden. Über die Property ConflictEventArgs.Cancel kann der Import
der entsprechenden Entität abgebrochen werden.
ThemiSyncExport bietet zur Information über den aktuellen Fortschritt während
eines Importvorgangs das Event
public event EventHandler<ImportProgressChangedEventArgs>
ImportProgressChanged;
Benutzerhandbuch
120
an.
Um vor dem Löschen einer importierenden Entität diverse Aktionen ausführen zu
können, wird das Event
public event EventHandler<BeforeDeleteEventArgs> BeforeDelete;
verwendet.
Abbildungsverzeichnis
Abbildung 1: Ablauf allgemeiner Synchronisationsvorgang ..................................... 16
Abbildung 2: Anwendungsfälle ................................................................................. 17
Abbildung 3: Softwareverteilung ............................................................................... 21
Abbildung 4: Systemaufbau ....................................................................................... 22
Abbildung 5: VelocityManager Zugriffsmöglichkeiten ............................................. 26
Abbildung 6: Einfaches Synchronisations-Beispiel Variante 1 ................................. 30
Abbildung 7: Einfaches Synchronisations-Beispiel Variante 2 ................................. 32
Abbildung 8: Synchronisations-Beispiel mit Konflikten ........................................... 34
Abbildung 9: Synchronisations-Beispiel mit mehreren Teilnehmern ........................ 36
Abbildung 10: Komponentenarchitektur Überblick................................................... 40
Abbildung 11: Package ThemiSync Übersicht .......................................................... 41
Abbildung 12: Datenmodell Grundstruktur ............................................................... 43
Abbildung 13: Diverse Klassen ................................................................................. 45
Abbildung 14: Datenmodell Synchronization ............................................................ 46
Abbildung 15: Datenmodell Utils .............................................................................. 47
Abbildung 16: Datenmodell Exceptions .................................................................... 48
Abbildung 17: Configuration Klassenhierarchie - vereinfachte Darstellung ............. 49
Abbildung 18: Konfigurationsgruppen - vereinfachte Darstellung ........................... 51
Abbildung 19: Ablauf Exportvorgang ....................................................................... 52
Abbildung 20: Objekthierarchie ................................................................................. 54
Abbildung 21: Klassendiagramm Initialisierung ....................................................... 56
Abbildungsverzeichnis
Abbildung
22:
122
Sequenzdiagramm
zum
Visualisieren
eines
vollständigen
Initialisierungsvorgangs ............................................................................................. 57
Abbildung 23: Datenmodell Metadaten-spezifische Klassen .................................... 61
Abbildung 24: Konfiguration Technisches Klassendiagramm .................................. 68
Abbildung 25: Beispiel für ein ExportConfigurationEntity Objekt ........................... 72
Abbildung 26: Beispiel für ein VelocityManager Objekt .......................................... 72
Abbildung 27: Klassendiagramm Export ................................................................... 73
Abbildung 28: Datenmodell Transport-Container ..................................................... 77
Abbildung
29:
Sequenzdiagramm
zum
Visualisieren
des
Exportvorgangs
(Querformat) .............................................................................................................. 78
Abbildung 30: Klassendiagramm Import ................................................................... 79
Abbildung
31:
Sequenzdiagramm
zum
Visualisieren
des
Importvorgangs
(Querformat) .............................................................................................................. 83
Abbildung 32: Projektphasen Qualitätsmanagement ................................................. 92
Abbildung 33: Beispielapplikation UML Diagramm ................................................ 98
Abbildung 34: ThemiSync Configurationtool ......................................................... 100
Abbildung 35: ThemiSync Datenbanktabellen Übersicht ........................................ 101
Abbildung 36: Beispielapplikation Tabellen ........................................................... 103
Abbildung 37: IBOF Generator ............................................................................... 104
Abbildung 38: Datenmodell ThemiSync Konfiguration .......................................... 107
Abbildung 39: Datenmodell Infpro.ThemiSync ...................................................... 116
Literaturverzeichnis
[San 09]
S. Sanderson, Pro ASP.NET MVC Framework, 1. Auflage, Apress
Verlag, USA, 2009
[KemEik 06]
A. Kemper/A.Eickler, Datenbanksysteme – Eine Einführung, 6.
Auflage, Oldenbourg Wissenschaftsverlag GmbH, München, 2006
[Tro 07]
A. Troelsen, Pro C# 2008 and the .NET 3.5 platform, 4. Auflage,
Apress Verlag, USA 2007