GNavigia und Datenbanken
Programmieren Sie eine Datenbankanbindung mittels COM
Dies Variante wird so nicht mehr unterstützt.
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;
}