GNavigia und Datenbanken
Programmieren Sie eine Datenbankanbindung mittels COM


Wer sich mit dem Component Object Model,
kurz «COM», auskennt, kann eine unabhängige, zur
Laufzeit nachladbare
Datenbankanbindung für GNavigia schreiben. Unter .NET geht das
ohne
Zweifel komfortabler, ist aber nicht zwingend erforderlich. Eine
Beispielanbindung, von
der .NET-Programme ableiten können, liegt GNavigia unter dem Namen
GpsDatabaseAccess
bei. Wenn Sie die Bezeichnung «Datenbankanbindung» sehr
weit fassen,
können Sie praktisch alle Arten von Auswertungen auf den Daten
aufsetzten.
Das Objekt muss dazu lediglich einen parameterlosen
Konstruktor sowie die IGpsDatabaseAccess Schnittstelle
implementieren und die Registrierung als COM Objekt um den
Unterschlüssel
{8BE02F24-766C-4ba3-A744-42FF0E3F8564}
erweitern. Wer von der o.a. Klasse ableitet, erhält die Erzeugung
des
Unterschlüssels «frei Haus». Vorsicht:
Für Ihre eigene
Datenbankklasse benötigen Sie eine andere, neue GUID! Eine GUID
erzeugt
man mit dem Programm GUIDGEN.EXE, dass man über Google auf
den
Seiten von Microsoft findet. Es sollte bei allen
COM-Entwicklungstools dabei sein! Ggf. generiert das Neuanlegen eines
.NET Projekts, das für COM registriert wird, eine solche GUID in
der
Datei AssemblyInfo.cs.
Die GUID wird ausgewertet, wenn im Menü
«Extras/Datenbankanbindung» gewählt
wird. Es erscheint dann eine Liste aller Objekte zur Auswahl, die
diesen Unterschlüssel angeben. Die Auflistung dauert einen kleinen
Moment. Der dargestellte Name ist der des COM Objekts, auch als
«Prog-ID» bezeichnet; intern wird die GUID gespeichert.
Wenn Sie
eine Anbindung geschrieben haben, die zumindest den korrekten
Konstruktor und die erforderlichen Methoden implementiert sowie die
o.a. Voraussetzungen erfüllt, erscheint nach der Auswahl ein
weiterer
Menüpunkt «Datenbank», der die abgebildeten
Untermenüpunkte enthält.
Zur Registrierung des COM-Objekts muss der Entwickler
über Administratorrechte verfügen, da die
Einträge unter
HKEY_CLASSES_ROOT erfolgen. Wer nicht als Administrator entwickeln
will, der kann, zumindest unter .NET, zur ersten Registrierung die
Entwicklungsumgebung als Adminstrator starten und danach die Option
«Für COM registrieren» ausschalten. Die Registrierung
ist nur einmal
nötig, um das COM Objekt und das Interface bekannt zu machen,
danach
erfolgt die Entwicklung als ganz normale Klassenbibliothek.
Steuerung der Datenbankzugriffe
Die Funktionalität, die die Schnittstelle IGpsDatabaseAccess
zur Verfügung stellt, lässt
sich am Besten am aufgeklappten Menü dokumentieren; dabei liefern
die
Eigenschaften (Properties) die Texte für die Menüpunkte,
während die
Methoden die eigentliche Datenbankfunktionalität bereitstellen. GpsInitialize,
GpsSaveData und GpsLoadData werden
direkt aus dem Menü
aufgerufen. GpsConnect und GpsDisconnect werden zu
gegebener Zeit
gerufen, z.B. wenn der Benutzer die Datenbankanbindung wechselt, indem
er aus dem Menü «Extras/Datenbankanbindung» einen
anderen
Datenbankanschluss auswählt. Lediglich der Menüpunkt
«Abmelden von der
Datenbank», der intern GpsDisconnect aufruft, wird allein von
GNavigia
verwaltet.
Initialisierung des Menüs
Das Menü wird einerseits aus der Anfrage an die
Schnittstellenmethoden
initialisiert, andererseits aber auch aus Informationen aus der
Registrierungsdatenbank. Wenn eine gültige Datenbankverbindung
ausgewählt wird, erscheint sie beim Wiederaufstarten der
Applikation,
initialisiert aus der Registrierung.
Laden und Speichern der Daten
Zudem merkt sich GNavigia die Herkunft der Daten, weshalb nur beim
erstmaligen Sichern und aktivierter Datenbank zwischen dem Speichern in
die Datenbank und dem in eine Datei unterschieden werden muss. Wenn Sie
sich für eine Datei als Speicherort entschieden haben, können
Sie immer
noch aus dem Menü das Zurückschreiben der Daten in die
Datenbank
veranlassen, wodurch jedoch nur der aktuelle Stand gesichert wird. Beim
Beantworten einer Sicherheitsabfrage wird folgerichtig nur in die Datei
geschrieben.
Die IGpsDatabaseAccess Schnittstelle
Die IGpsDatabaseAccess Schnittstelle ist bewusst einfach
gehalten,
sodass COM Server keine .NET Interna kennen müssen. Was sie kennen
müssen ist jedoch die interne Datenstruktur von GNavigia, was
wegen der
XML-Struktur, mit der alle Daten über die Schnittstelle
ausgetauscht
werden, aber sehr flexibel gehandhabt werden kann. Das Interface ist
wie folgt definiert:
public interface IGpsDatabaseAccess { // Read only property: The database name string GpsDatabaseName { get;}
// Read only property: An appropriate title string GpsDatabaseTitle { get;}
// Read only property: A kind of tooltip string GpsDatabaseHint { get;}
// Read only property: Menu item text for GpsInitialize string GpsInitializeMenuText { get;}
// Read only property: Menu item text for GpsSaveData string GpsSaveDataMenuText { get;}
// Read only property: Menu item text for GpsLoadData string GpsLoadDataMenuText { get;}
// Menue called method to initialize database access. // returns: XmlDocuments.Response() if successfull string GpsInitialize(int hwnd);
// Menue called method to connect to the database. // returns: XmlDocuments.Response() if successfull string GpsConnect(int hwnd);
// Menue called method to disconnect from the database // returns: XmlDocuments.Response() if successfull string GpsDisconnect(int hwnd);
// Menue called method to save data to database. // returns: XmlDocuments.Response() if successfull string GpsSaveData(int hwnd, string xmlDataString);
// Menue called method to load data from database. // returns: An XML Data Document String if successfull where the // string is a fully qualified XML document. // Mind the schema definition! string GpsLoadData(int hwnd); }
Der formale Parameter «hwnd» ist vom Typ int (Int32) und
repräsentiert
jenes Windowhandle, das die Urgesteine der Fensterprogrammierung seit
den ausgehenden 80er Jahren des vorigen Jahrhunderts kennen sollten. Es
hat nur einen einzigen Wert, nämlich einen eventuell notwendigen
Dialog
an einem Fenster festmachen zu können und so die Kette der durch
modale
Dialoge abgeschalteten Fenster nicht zu unterbrechen. Der
.NET-Programmierer kann das Handle direkt nutzen, indem er ein Objekt
der fensternahen Klasse «TemporaryOwner» anlegt, die
selbst
wiederum keine andere Aufgabe hat, als die Schnittstelle
«IWin32Window»
bereitzustellen, die ihrerseits keine andere Aufgabe hat, als das
Windowhandle verfügbar zu machen. COM Programmierer haben es an
dieser
(und nur an dieser) Stelle einfacher: Sie casten den Wert auf HWND und
können ihn als parent window handle benutzen.
Rückgabewerte
Werfen Sie niemals eine Ausnahme (Exception), die die Schnittstelle
verlässt. Sorgen Sie dafür, dass die Ausnahmen innerhalb der
Schnittstelle bleiben und benutzen Sie die vorgesehenen XML-Dokumente
als Rückgabewerte, also «Response» und
«ErrorResponse». Wer .NET
benutzt, kann die entsprechenden Methoden der
KorKarNet.Utilities.dll
aufrufen. Damit ist das Verpacken der Information besonders einfach.
Allerdings bleibt die Aufgabe bestehen, die Daten zu einem GNavigia
konformen XML-Dokument zusammenzustellen. Das Thema «GNavigia
für
Fortgeschrittene» widmet sich diesem anspruchsvollen Thema.
Der harte Kern der Datenbankanbindung
Die Datenbankanbindung stellt im Kern zwei
Methoden zur Verfügung, die die Arbeit des Datenaustauschs
übernehmen:
string GpsSaveData(int hwnd, string xmlDataString); string GpsLoadData(int hwnd);
Daten in der Datenbank speichern
Widmen wir uns zunächst dem Speichern von Daten. Hier macht es
sich
GNavigia besonders einfach, indem es exakt denselben Dokumentinhalt in
eine Zeichenkette verpackt, die das Programm auch auf Datei ausgeben
würde.
Ob eine Datenbankanwendung die Informationen über Objekte und
Layout
auswerten will oder nur die primären Daten (Tracks, Trackpunkte
und
Wegpunkte) berücksichtigt, ist letztlich jeder Applikation selbst
überlassen. Eine Mischung aus dateigestützter
Layoutdefinition und
datenbankgespeicherter Punktinformation ist nicht möglich. Denkbar
ist,
dass die Datenbankapplikation die Layoutdefinition in einer
geschlossenen Zeichenkette im XML-Format in die Datenbank schreibt.
Allerdings ist dann eine Zuordnung von Primär- und Layoutdaten nur
durch eine Auftragsverwaltung zu realisieren, die hier nicht behandelt
wird.
Der Rückgabewert der Methode GpsSaveData ist eine
XML-Zeichenkette, die
die Liste der neu in die Datenbank eingetragenen Punkte enthält.
Diese
bekommen beim Insert eine neue, datenbankinterne ID, hier als global
gültige ID (GUID) bezeichnet, die GNavigia mitgeteilt werden muss.
Diese Aufgabe übernimmt das Tag «Identifier» in der
Antwort auf die
Anfrage:
<Identifier iid="312" guid="AXZ67900jsds00" />
Darin ist «iid» die GNavigia-ID des Punktes und
«guid» der globally
unique identifier, den Sie als Benutzer vergeben haben, um das Objekt
in der Datenbank identifizieren zu können, sollte also
datenbankweit
eindeutig sein! Sie erhalten Aufschluss über die syntaktisch
korrekte
Ausgabe/Platzierung der GUID, indem Sie das Programm mit dem Parameter
-guid
auf der Kommandozeile aufrufen und eine Datei mit mindestens einem
Wegpunkt, Track, Trackpunkt, Objekt, Textobjekt und einer
Objektreferenz speichern. Ansonsten wird eine leere, undefinierte GUID
nicht in die Datei geschrieben. Bei dieser Simulation erhält die
GUID
den Wert «"#Invalid"», der später beim Einlesen der
Datei wieder in
einen leeren Wert überführt wird.
Daten aus der Datenbank laden
Prinzipiell ist das Ladeformat identisch
mit dem Speicherformat, doch liegen beim Laden nur die erfassten,
externen Informationen vor, sodass die Daten kompakter auftreten. Dabei
handelt es sich um das bereits zuvor erwähnte XML-Dokument, das
durch
eine
Schemadatei validiert werden kann. Die Schemadatei ist allerdings
noch nicht realisiert. Wenn Sie sich die Datenstruktur im Abschnitt
«GNavigia
für
Fortgeschrittene» genauer ansehen, werden Sie feststellen,
dass Sie
für die Nachbildung der Datendateien eine wie auch immer geartete
Auftragsverwaltung benötigen, die die primären Beobachtungen
und die
Objektbildung, die Sie im Laufe der Zeit vornehmen, zu einer ladbaren
Datenstruktur zusammenstellt.
Eigene Einstellungen transportieren
Damit Sie Einstellungen und eigene Vorgaben aus der Lademethode in die
Speichermethode übertragen können, können Sie in die
Ladedatei eine
Eigendatenkennung eintragen. XML-Elemente, die sich zwischen den
Markierungen
<Database> </Database>
befinden, werden vom Programm als Ganzes gelesen, aber nicht
interpretiert. Beim Ausgeben der Daten als Datei oder beim
Zurückschreiben in die Datenbank wird dieses Tag wieder
ausgegeben.
Damit ist es möglich, ohne den Gebrauch globaler Variablen
Daten zwischen den Methoden zum Laden und Speichern zu transportieren.
Hilfsfunktionen
Beispiel für die Verwendung der Klasse TemporaryOwner:
string IDatabaseAccess.GpsSaveData(int hwnd, string xmlDataString); { MessageBox.Show(new TemporaryOwner(hwnd), String.Format("The method received a string of {0} bytes.", xmlDataString.Length)); return null; }
|