Views / Client Server
Norbert Abb
Das Kapitel über Views (Ansichten) zeigt, wie Views erstellt, modifiziert und verwendet werden. Außerdem gibt es einen Einblick, welche Bedeutung Remote-Views für die
Client-Server-Programmierung haben.
Was sind Views?
Ein View ist eine definierte Sichtweise auf Daten. Das bedeutet, ein View ist in der Lage, Daten aus einer oder mehreren Tabellen darzustellen und zu filtern.
Betrachten wir zuerst den Fall, daß nur eine Tabelle in einem View verwendet wird. Die Tabelle besteht zum Beispiel aus den Spalten Name, Vorname, Ort und PLZ. Der View enthält aber
nur die Spalten Name und Vorname. Außerdem kann ein View auch die Datensätze der Tabelle filtern. So ist es möglich, nur die Datensätze darzustellen, bei denen die Werte der Spalte
Name mit "A" beginnen. Komplexe Views können Spalten aus mehreren Tabellen beinhalten.
Die Definition eines Views ist im Datenbank-Container festgehalten. Visual FoxPro unterscheidet zwischen local Views und remote Views (lokalen und entfernten Ansichten). Local Views
basieren auf FoxPro-Tabellen, remote Views verwenden als Quelle Tabellen einer ODBC-Verbindung. Das Ergebnis eines Views ist eine temporäre Tabelle, die als CURSOR (CURrent Set
Of Records) bezeichnet wird. Auf einen Cursor können die normalen FoxPro-Befehle (Skip, Scan, Locate, etc.) angewendet werden. Damit ist es möglich, Daten aus ODBC-Quellen mit
FoxPro-Befehlen zu verändern. Ein View ist auch als Grundlage der Datenumgebung einer Maske einsetzbar. Das heißt, die Maske bezieht ihre Daten aus dem View (Cursor) und kann die
Daten bearbeiten. Ein View besitzt die Möglichkeit, Daten anderer Datenbanken (insbesondere Server Datenbanken) zu sehen und zu verändern, sofern für diese Datenbank ein ODBC
Treiber installiert ist.
Der View Designer (Ansichtsdesigner)
Die Definition eines Views ist am einfachsten über den Projektmanager durchzuführen: Im Register <Daten> einen Datenbank-Container aufklappen und "lokale" oder "remote" Ansichten
auswählen. Mit "Neu" wird der View Designer aufgerufen.
Arbeiteniten mit dem View Designer
Das Fenster des View Designers besteht aus zwei Teilbereichen. Der obere Fensterbereich enthält die Quell-Tabellen, der untere Bereich eine Pageframe mit fünf Seiten.
Auf der ersten Seite sehen wir die Auswahlkriterien (Filterkriterien) für die Abfrage. Verwendbar sind Felder von Tabellen und Konstanten. Die Bedingungen können auch
Speichervariablen enthalten, diese sind mit "?Variablenname" anzugeben. Mehrere Bedingungen werden mit AND und/oder OR verknüpft. Kreuzen wir das Feld <NICHT> an,
berücksichtigt Visual FoxPro nur diejenigen Datensätze, auf die diese Bedingung nicht zutrifft. Das Markierfeld <groß/klein> gibt vor, ob zwischen Groß- und Kleinschreibung zu
unterscheiden ist.
Auf der Seite 'Felder' des Designers werden die Felder ausgewählt, die der (Ergebnis-) Cursor enthalten soll. Die Auswahl der Felder erfolgt über einen Doppelklick, per Drag and Drop
oder über die Schaltflächen. Außerdem sind auch berechnete Felder (Spalten) - wie z.B. Summe, Mittelwert etc. - möglich. Das rechte Listenfeld zeigt die Spalten des Views. Die
Reihenfolge der Einträge in diesem Listenfeld ist auch die Reihenfolge der Spalten im Cursor. Diese Reihenfolge läßt sich mit Hilfe des Knopfes vor dem Listeneintrag verändern. Die
Reihenfolge, in der die Datensätze einer Abfrage präsentiert werden, ist auf der dritten Seite der Designer-Maske vorzugeben. Dort lassen sich per Doppelklick die Felder bestimmen, nach
der die Abfrage zu sortieren ist. Bei jeder Sortierbedingung ist die Angabe möglich, ob die Sortierung in aufsteigender oder absteigender Reihenfolge erfolgt.
Mit Hilfe der Seite "Gruppierung" des Ansichtsdesigners können Gruppen von Datensätzen zusammengefaßt werden. Damit sind Rechenfunktionen in den Spalten der Abfrage über
Datengruppen möglich. Das Ergebnis einer Gruppierung ist durch Filterbedingungen (Having-Klausel) beeinflußbar.
Mehrere Tabellen (Verknüpfung)
Weitere Tabellen fügen wir über die Designer-Toolbar oder das Abfrage-Menü hinzu. Alternativ steht auch das Kontextmenue (Klick mit rechter Maustaste) zur Verfügung. Das
anschließende Fenster dient zur Auswahl der hinzuzufügenden Tabelle. Die Tabelle muß nicht im aktuellen Datenbank-Container sein - über das Drop- Down-Feld <Datenbank> kann
auch eine andere Datenbank angewählt werden. Das Listenfeld enthält die Tabellen der ausgewählten Datenbank. Außer Tabellen stehen auch bestehende Ansichten zur Verfügung. Das
Hinzufügen von freien Tabellen ist über die Schaltfläche <andere> möglich.
Nach dem Hinzufügen bietet der Designer dem Anwender eine Verbindung (Join) der beiden Tabellen an, sofern in der Datenbank eine Verbindung zwischen den beiden Tabellen besteht
oder ein gleichnamiges Feld vorhanden ist. Die angezeigte Bedingung stellt die Verknüpfung der beiden Tabellen dar und wird den Auswahlkriterien hinzugefügt.
In allen Seiten des Designers stehen nun die Spalten der beiden Tabellen zur Verfügung.
Die Abfrage
Der Ansichtsdesigner erstellt aus den Angaben der Maske eine Abfrage in SQL - der Standard-Abfragesprache für Datenbanken. Dieser SQL-Befehl kann über den 'SQL' -Knopf in der
Toolbar auf dem Bildschirm eingesehen werden. Der angezeigte SQL-Befehl ist in dem Fenster nicht veränderbar, stellt jedoch eine gute Kontrolle des generierten Befehls dar.
Programmatische Erstellung einer Ansicht
Visual FoxPro enthält zur programmatischen Erstellung einer Ansicht folgenden Befehl:
Create SQL View <Name der Ansicht> as Select ... from ... .
Vor der Erstellung einer Ansicht muß die entsprechende Datenbank geöffnet sein. Der Befehl hierfür lautet:
Open Database <Datenbankname>.
Tabellen aus anderen Datenbanken sind wie folgt anzugeben:
<Datenbank>!<Tabelle>.
Das Erstellen einer Remote-Ansicht erfordert noch die Angabe der Verbindung zu der 'remote' Datenquelle. Der Verbindungsname ist nach dem Ansichtsnamen einzusetzen:
Create SQL View <Name der Ansicht> Connection <Verbindungsname> as Select ... from ... .
Aktualisieren von Daten in einer Ansicht
Beim Erstellen einer Ansicht über den View-Designer ermöglicht die Seite Aktualisierung die Steuerung der Aktualisierung der zugrundeliegenden Tabellen. Auf dieser Seite sind die
Einstellungen vorzunehmen, wie und welche Daten der Ansicht veränderbar sind.
Damit änderungen in die Originaltabellen geschrieben werden, muß das Markierfeld <SQL-Aktualisierungen senden> angekreuzt sein! Das Markierfeld steht allerdings erst zur
Verfügung, nachdem ein Schlüsselfeld und mindestens ein zu aktualisierendes Feld in der Feldliste angegeben ist. Das Schlüsselfeld ist normalerweise durch den Primärschlüssel einer
Tabelle vorgegeben - das Schlüsselfeld muß nicht unbedingt eindeutig sein!
Die Art und Weise der Aktualisierung von Datensätzen in den Originaltabellen ist über die Einstellung <Aktualisierung durch> vorzugeben. Die Vorgabe <SQL UPDATE> erzeugt den
SQL-Befehl Update. Die Einstellung < SQL DELETE, dann INSERT> führt zuerst das SQL Delete Statement aus, anschließend wird der geänderte Datensatz über ein SQL-Insert wieder
hinzugefügt. Diese Option ist eventuell bei ODBC-Datenquellen notwendig, da nicht alle Datenbank-Server den Update-Befehl unterstützen.
Die Funktion 'TableUpdate()' bewirkt das Schreiben der aktualisierten Daten in die Originaltabelle. Ansichten verwenden implizit ein optimistisches Sperren von Datensätzen, das
bedeutet, daß ein Table Update nur dann erfolgreich ist, wenn die zugrundeliegenden Daten noch im Originalzustand sind. Die Funktion 'TableRevert()' stellt den Originalzustand der
Daten wieder her.
Aktualisierungskonflikte
Wie bereits angesprochen ist bei der Verwendung von Ansichten nur optimistisches Sperren möglich. Hierbei ist zwischen Sperrungen auf Satzebene und Tabellenebene zu
unterscheiden. Lokale Ansichten unterstützen beide Sperrmechanismen, Remote-Views unterstützen nur Sperrungen auf Tabellenebene. Pessimistische Sperrungen sind nur bei lokalen
Tabellen möglich. Bei der pessimistischen Sperrung von Datensätzen finden die Sperrversuche bei der Eingabe von Daten statt. Das heißt, ist eine Sperrung nicht erfolgreich, sind
änderungen nicht möglich. Die Sperrung bleibt solange erhalten, bis der Benutzer den Datensatz frei gibt.
Das optimistische Sperren läßt änderungen von Daten zu, das Sperren der Datensätze findet erst beim Speichern der Daten statt. Sind die Sperrversuche erfolglos, oder die Daten sind
zwischenzeitlich geändert worden, muß der Benutzer - oder Programmierer - entsprechend reagieren. Sind pessimistische Sperrungen bei Ansichten erwünscht, so muß dies vom
Entwickler selbst programmiert werden.
Kriterien zur Aktualisierung
Die Einstellung <SQL WHERE-Klausel enthält> bestimmt, wie Konflikte bei Datenänderungen festgestellt werden.
Bei der Einstellung <Nur Schlüsselfelder> wird nur geprüft, ob der entsprechende Wert im Schlüsselfeld der Tabelle noch existiert: ... WHERE Kunden.
Kunden_nr = Kview. Kunden_Nr
Bei der Einstellung <Schlüssel und aktualisierbare Felder> werden außer dem Schlüssel alle Felder, die in der Ansicht aktualisierbar sind, mit Gleichheitsbedingung in die WHERE-Klausel
aufgenommen. Das gibt die Sicherheit, daß keine anderen änderungen über diesen View geschehen sein können.
Absolute Sicherheit bietet jedoch nur die Kontrolle über den Zeitstempel. Dazu müssen alle Tabellen in der Ansicht, die verändert werden sollen, einen Zeitstempel besitzen. Diese
Einstellung wird nur bei remote Views mit Servern unterstützt.
Die Einstellung 'Schlüssel und aktualisierte Felder' nimmt außer dem Schlüsselfeld noch alle tatsächlich veränderten Felder in die WHERE-Klausel auf.
Client/Server Aspekte
Die Verwendung von Remote Views erfordert eine definierte Verbindung zu einer ODBC-Datenquelle. Die Definition einer ODBC-Datenquelle erfolgt im ODBC-Administrator (eigene
Applikation oder in der Systemsteuerung). Das Erstellen einer Verbindung zu der ODBC-Datenquelle ist mit dem Connection Designer vorzunehmen. Hier geben wir die Datenquelle (dsn),
die Benutzerkennung (uid) und das Paßwort (pwd) an. Diese Angaben erfolgen entweder als einzeln zu setzende Parameter oder mittels einer Verbindungszeichenfolge (Connection
String), die diese Parameter enthält. Bei anderen Servern als dem MS SQL-Server wird es oft nötig sein, mit dem Connection String zu arbeiten, um die Datenbank, mit der man arbeiten
möchte, zu spezifizieren. Ein Connection String sieht dann beispielsweise so aus:
dsn=Pubs;uid=sa;pwd=boss.
Weitere Parameter für Verbindungen
Asynchrone Verarbeitung
Normalerweise erhält ein Programm die Kontrolle wieder, nachdem der ODBC Befehl vollständig abgearbeitet ist. Die asynchrone Verarbeitung setzt den SQL-Befehl ab und gibt die
Kontrolle an das Programm zurück. Das Programm muß später nachprüfen, ob der ODBC-Befehl erfolgreich war.
Batch Modus
Im Batch Modus werden die Ergebnisse nach der Abarbeitung von SQL-Statements vom Server nur zusammen geliefert. Der non-Batch Modus ist für den Fall interessant, wenn mehrere
Cursor mit einem Statement aufgebaut werden. Im non-Batch Modus werden Ergebnisse bereits nach dem Abarbeiten des ersten Select Statements geliefert.
Automatische Transaktionen
Ist diese Option gesetzt, wird jedes abgesetzte SQL Statement als eine eigene Transaktion aufgefaßt (oft auch als Autocommit bezeichnet). Ohne diese Option muß die
Transaktionskontrolle manuell (programmatisch) erfolgen. Das bedeutet, am Ende einer Transaktion ist ein Commit oder ein Rollback durchzuführen. Der Server beginnt mit dem ersten
Befehl danach eine neue Transaktion (genauso wie bei der ersten Anweisung) - es gibt also kein 'Begin Transaction'. Diese Parameter können zur Laufzeit noch mit 'SQLSetProp()'
verändert werden.
Ein weiterer Verbindungsparameter ist die Anzahl der Datensätze (Fetch Size), die FoxPro vom Server als Block erhalten soll. Der Standardwert für die Fetch Size ist auf 100 eingestellt. Das
bedeutet, FoxPro zeigt z.B. das Browse Fenster (oder eine Maske) an, sobald die ersten hundert Sätze gefunden sind. Der Benutzer kann dann bereits auf den Daten arbeiten, während
FoxPro im Hintergrund noch weitere Datensätze vom Server erhält. Dies ermöglicht - selbst bei einem komplexen Cursor - Daten zu präsentieren, obwohl der Cursor noch nicht vollständig
aufgebaut ist. Es ist dabei aber zu beachten, daß die Daten tatsächlich auf die Workstation kopiert werden. Ist der Cursor zu groß für den Hauptspeicher, lagert FoxPro die Daten auf die
Festplatte aus. Es empfiehlt sich also nicht, riesige Tabellen vollständig vom Server auf den PC zu kopieren. Die maximale Anzahl von Datensätzen, die ein Cursor enthalten kann, ist über
den Parameter 'MaxRecords' vorzugeben. Damit wird ein Limit für die Ergebnismenge gesetzt.
Weitere Parameter für Remote Views, die positiv auf die Performance wirken: "Memofeld abrufen" (FetchMemo) und "Memofeld verwenden für Felder >=" (UseMemoSize).
Der Server kennt keine Memofelder im Sinne von FoxPro. Der Parameter "UseMemoSize" bestimmt, ab welcher Feldlänge ein Feld als Memofeld zu betrachten ist. FetchMemo gibt vor, ob
Memo-Felder sofort übertragen oder erst durch eine getrennte Abfrage geholt werden. Die Speicherung dieser Parameter erfolgt im Datenbankcontainer. Diese Einstellungen sind mit dem
Designer oder programmatisch mit der Funktion DBSetProp() vorzunehmen, können aber auch zur Laufzeit dynamisch mit der Funktion CursorSetProp() angepaßt werden.
Allgemein gilt für die Client/Server Programmierung: Man hat mit Visual FoxPro ein Werkzeug, das sehr komfortabel eine Client/Server Architektur ermöglicht. AufgaEntwicklers ist es, durch sein Systemdesign darauf zu achten, die Resourcen im Netzwerk möglichst wenig zu belasten.
Norbert Abb hat Informatik an der TH Darmstadt studiert. Der Schwerpunkt seines Studiums lag im Bereich Datenbanken. Er war unter anderem auf einem Projekt von Andersen Consulting für eine große deutsche Kreditkartengesellschaft
tätig. Seit dem 1.1.1995 ist er selbständig und Gesellschafter der Wizards & Builders GmbH. Er hat bereits mehrere Workshops für die dFPUG zu Visual FoxPro durchgeführt.
CopyRight © 1996 by dFPUG c/o ISYS GmbH bzw. Beim entsprechenden Verfasser
|