Session D-LORELokale und Remote ViewsNathalie Mengel
|
Zweck | View-Eigenschaft (1) | Cursor-Eigenschaft (2) |
---|---|---|
Zulassen einer Tabelle zum Aktualisieren | Tables | Tables |
Angeben der Remote-Namen der Felder einer Ansicht | UpdateName (Eigenschaft auf Feldebene) | UpdateNameList |
Angeben der Felder einer Ansicht, die Sie als Schlüssel verwenden möchten | KeyField (Eigenschaft auf Feldebene) | KeyFieldList |
Angeben der aktualisierbaren Felder einer Ansicht | Updatable (Eigenschaft auf Feldebene) | UpdatableFieldList |
Aktivieren von Aktualisierungen | SendUpdates | SendUpdates |
(1) Wird mit DBSETPROP( ) festgelegt.
(2) Wird mit CURSORSETPROP( ) festgelegt.
Sie können einen geöffneten View wie eine normale Visual Foxpro - Tabelle behandeln. Sie haben hier also die Wahlmöglichkeit, ob Sie Datensätze mit SQL-Befehlen oder FoxPro-Befehlen bearbeiten. Der gute alte APPEND BLANK und REPLACE funktionieren wie gewohnt. Nur zum Schreiben der Daten in die Ursprungstabelle sollten sie noch etwas beachten. Natürlich könnten Sie einfach die Form schließen oder den Datensatzzeiger bewegen, um die Aktualisierung anzustoßen. Aber dann hätten Sie keine Kontrolle darüber, ob Ihre Änderungen tatsächlich in der Ursprungstabelle angekommen sind oder nicht. Also benutzen wir die Funktion TABLEUPDATE(), um das Update anzustoßen. TABLEUPDATE() gibt .T. oder .F. zurück, jenachdem, ob das Update erfolgreich war oder nicht.
Wenn Sie vergessen, die SendUpdates-Eigenschaft des Cursors/Views auf .T. zu setzen, ist TABLEUPDATE()=.T., obwohl das Update gar nicht gesendet wurde! |
Wenn TABLEUPDATE() nicht erfolgreich war, können Sie den Fehler über AERROR() abfangen und auswerten. Fehlerquellen können zum Beispiel Verletzungen von Referentieller Integrität oder Aktualisierungskonflikte sein.
Wenn das TABLEUPDATE() nicht erfolgreich war und der Fehler nicht zu beheben ist, müssen Sie die Änderungen mit TABLEREVERT() wieder rückgängig machen.
Um mit Views arbeiten zu können, muß die Tabellen- oder Zeilenpufferung in VFP eingeschaltet sein. Grundsätzlich muß man dafür zunächst SET MULTILOCKS ON schalten. Views arbeiten standardmäßig mit optimistischer Zeilenpufferung, was bedeutet, daß die zu ändernde Zeile nur in dem Moment gesperrt wird, in dem sie weggeschrieben werden soll. Grids arbeiten grundsätzlich mit optimistischer Tabellenpufferung, so daß man nicht jeden Satz einzeln wegschreiben muß. In den allermeisten Fällen reicht das optimistische Pufferungsmodell aus, zumal Aktualisierungskonflikte von der Datenbank erkannt werden können.
Folgende Buffermodes sind für lokale Views möglich:
Wenn man mehrere Tabellen abhängig voneinander aktualisieren will, kann es sinnvoll sein, die Aktualisierung in eine Transaktion einzuschließen. Die Transaktion wird mit BEGIN TRANSACTION gestartet. Schlägt dann ein TABLEUPDATE() fehl, so kann man die bisher durchgeführten Änderungen durch ROLLBACK wieder rückgängig machen. Klappt alles, so beendet man die Transaktion durch END TRANSACTION. VFP unterstützt bis zu fünf Transaktionslevels, so daß man die Transaktionen auch schachteln kann.
Ähnlich wie der lokale View ist ein Remote View eine Ansichtsdefinition, die sich in einer VFP-Datenbank befindet. Wenn man sie öffnet, wird ebenfalls ein Cursor erstellt, auf dem man genauso arbeiten kann, als handle es sich um VFP-Daten. Der Unterschied besteht eigentlich nur darin, daß der Remote View nicht auf Daten aus einer Tabelle, die sich in einer VFP-Datenbank befindet, zugreift, sondern daß die Datenquelle grundsätzlich irgendeine relationale Datenbank sein kann. Auf diese Backend-Datenquelle wird von der Frontend-VFP-Anwendung über einen ODBC-Treiber als verbindende Middleware zugegriffen.
Die Arbeit mit Remote Views unterscheidet sich gar nicht so sehr von den lokalen Views. Wie Sie in der Abbildlung sehen, besteht für die VFP-Anwendung eigentlich gar kein Unterschied. Sie arbeitet weiterhin auf einem temporären Cursor, dessen Eigenschaften genauso gelesen, bzw. geschrieben werden können, als basiere dieser Cursor auf einem lokalen View. Lediglich die Viewdefinition in der VFP-Datenbank und die Herkunft der Daten unterscheiden sich etwas von den lokalen Views. Aber der Anwendung selbst kann das (fast) egal sein.
Die Besprechung des Upsizing-Assistenten würde hier den Rahmen sprengen. Sie können sein Funktionalität im Handbuch nachlesen oder ihn einfach ausprobieren. Mag er vielleicht ein noch so gutes Instrument zum Upsizing sein, wir wollen hier vor allem die grundsätzlichen Aspekte beleuchten, die Sie vor dem Upsizing, bzw. in der Planung der Datenbank beachten sollten.
Wenn Sie eine Datenbank planen, die entweder sofort oder später auf einem Client/Server Datenbanksystem liegen soll, so sollten Sie sich von Anfang an über die Möglichkeiten des Datenbanksystems informieren und stets den kleinsten gemeinsamen Nenner verfolgen. Die schönste durchgeplante VFP-Datenbank wird Ihnen keine Freude machen, wenn sie zum Beispiel auf Oracle 7 umgestellt werden soll und ihre Tabellen mehr als ein Memo-Feld enthalten, logische Datenfelder enthalten, oder wenn ihre Views mehr als einen Outer-Join enthalten. Wie gesagt, Information über das zukünftige Back-End ist alles und der kleinste gemeinsame Nenner gibt hier den Ton an.
Der ODBC-Treiber ist für uns das Tor zur Welt. Beachten Sie bitte, daß mit VFP zwar einige ODBC-Treiber mitgeliefert werden, daß aber die Originaltreiber der Datenbankhersteller meistens schneller und manchmal auch im Fehlerfall gesprächiger sind! Sie benötigen den installierten ODBC-Treiber und dazu einen eingerichteten DSN ("Data Source Name" oder "ODBC-Datenquelle"). Über diesen DSN wird die Verbindung zur Datenquelle hergestellt.
Connections sind Definitionen von benannten Verbindungen, die in der VFP-Datenbank gespeichert werden. Sie können Connections über den Verbindungsdesigner oder durch den Befehl CREATE CONNECTION erstellen. Der Name der Connection wird bei der Definition eines Remote View angegeben.
Datentypen
Beispielhaft haben wir hier eine Datentypen-Vergleichstabelle für den Microsoft-SQL-Server angegeben.
SQL Server Type | Beschreibung | Domäne | Visual FoxPro Typ |
---|---|---|---|
binary(n) | fixed-length binary | 1-255 bytes | n/a |
bit | logical | 0 or 1 | logical |
char(n) | fixed-length | text 1-255 characters | character |
datetime | dates & time accurate to the millisecond | 1/1/1753 to 12/31/9999 | datetime |
decimal | exact numeric | -10E38 to 10E38-1 | n/a |
float | floating point | 1.7E-308 to 1.7E+308 | numeric, float, double |
image | variable-length binary | <= 2,147,483,647 bytes | general |
int | integer | -2,147,483,648 to 2,147,483,647 | integer |
money | monetary | -922,337,203,685,477.5808 to 922,337,203,685,477.5807 | currency |
numeric | exact numeric | -10E38 to 10E38-1 | n/a |
real | floating point | 3.4e-38 to 3.4e+38 | n/a |
smalldatetime | dates & time accurate to minutes | 1/1/1900 to 6/6/2079 | n/a |
smallint | integer | -32,768 to 32,767 | n/a |
smallmoney | monetary | -213,748.3648 to 214,748.3647 | n/a |
text | variable-length text | <= 2,147,483,647 characters | memo |
timestamp | automatically updated varbinary | (8) | n/a |
tinyint | integer | 0 to 255 | n/a |
varbinary(n) | variable-length binary | 1-255 bytes | n/a |
varchar() | variable-length text 1-255 characters | n/a |
Die Definition eines Remote-Views unterscheidet sich nur wenig von der eines lokalen Views. In unserem Beispiel sieht sie so aus:
CREATE SQL VIEW vkunden REMOTE; CONNECTION conn1 SHARE; AS SELECT kunden.* ; FROM kunden WHERE kunden.land = ? lcCountry
Wenn der View geöffnet wird, wird über benannte Verbindung conn1 eine Connection aktiviert. Unabhängig davon, ob mehrere Views dieselbe benannte Verbindung nutzen, kann entweder für jeden View eine neue Connection aktiviert werden oder eine Connection von mehreren Views genutzt werden. Dies ist vor allem dann von Interesse, wenn Client-Lizenzen über die Anzahl aktiver Connections abgerechnet werden (z.B. Oracle). Setzen Sie also in diesem Falle wie oben die ShareConnection Eigenschaft des Views.
Remote Views benutzen nur bereits aktive Connections, wenn diese ebenfalls shared durch einen anderen remote View geöffnet wurden. Wenn Sie eine Connection mit SQL Pass-Through öffnen, wird diese nicht von Remote Views genutzt (außer bei Access). |
Wenn Sie mit Shared Connections arbeiten, muß der Remote View stets
(außer bei Access) seine gesamte Ergebnismenge ziehen. Dafür
müssen die View-Eigenschaften MaxRecords und FetchSize auf -1 gesetzt
werden! Ansonsten erhält man beim Öffnen des Views die Fehlermeldung,
daß die Verbindung belegt sei. Dies widerspricht allen Regeln der
Vernunft und steht in krassem Widerspruch zu dem Bestreben, möglichst
wenig Daten über die Leitung zu schicken. Laut Microsoft ist dieses Verhalten aber BY DESIGN. (Gibt es da nicht noch die Session "Blame Microsoft"?) |
Im Prinzip ist ein geöffneter Remote View nichts weiter als ein Cursor mit Update-Eigenschaften. Deshalb kann er auch nicht automatisch die Remote-Datenbank sperren. Demzufolge stehen für remote Views nur die Buffermodes Optimistic Row und Optimistic Table zur Verfügung.
Transaktionen
Standardmäßig werden Updates von remote View mit automatischen Transaktionen durchgeführt. Das bedeutet, daß jedes Update eines remote Views automatisch commited wird. Wenn man Updates mehrerer Views in Transaktionen einschließen möchte, muß man zunächst die Transactions-Eigenschaft der Verbindung auf manuell umstellen. Dann kann man die Transaktionen manuell steuern.
Die BEGIN/END TRANSACTION - Befehle steuern nur die lokale VFP-Datenbank. Um auf der remote Server-Datenbank Transaktionen zu realisieren, muß man diese über SQL Pass-Through mit den Funktionen SQLCOMMIT() und SQLROLLBACK() steuern. |
SQL Pass-Through ist eine programmatische API für den direkten Zugriff auf Client/Server-Datenbanken. SPT kann nicht visuell generiert werden. Dafür kann man servereigene Syntax und Funktionen nutzen und hat jeden Zugriff selbst in der Hand.
Mit SQL Pass-Through kann man serverspezifische Elemente verwenden, wie z. B. gespeicherte Prozeduren sowie Funktionen, die nur der Server bereitstellt. Man kann neben den SQL-Erweiterungen, die der Server unterstützt, auch die Datendefinitions-, Serververwaltungs- und Sicherheitsbefehle verwenden. Mit SPT verfügt man über mehr Möglichkeiten zur Steuerung der Aktualisierungs-, Lösch- und Einfügebefehle. Außerdem kann man so Remote-Transaktionen steuern.
Hier die SQL Pass-Through Funktionen im Überblick:
Aufgabe | Funktion | Zweck |
---|---|---|
Verwaltung von Verbindungen | SQLCONNECT( ) | Stellt eine Verbindung zu einer Datenquelle für SQL Pass-Through-Operationen her. |
SQLSTRINGCONNECT( ) | Stellt eine Verbindung zu einer Datenquelle unter Verwendung der Syntax für Verbindungszeichenfolgen her. | |
SQLDISCONNECT( ) | Hebt eine Verbindung zu einer ODBC-Datenquelle auf, so daß die angegebene Verbindungskennung überflüssig wird. | |
Ausführung und Steuerung von SQL-Anweisungen | SQLCANCEL( ) | Bricht eine SQL-Abfrage ab, die asynchron über eine aktive Verbindung ausgeführt wird. |
SQLEXEC( ) | Führt eine SQL Pass-Through-Abfrage über eine aktive Verbindung aus; gibt die Anzahl der erstellten Ergebnismengen zurück oder 0, wenn die Ausführung von SQLEXEC ( ) noch andauert (asynchrone Verarbeitung). | |
SQLMORERESULTS( ) | Legt eine weitere Ergebnismenge in einem Cursor ab. Gibt 0 zurück, wenn die Ausführung der Anweisung, welche die Ergebnismenge erstellt, noch andauert. | |
SQLPREPARE( ) | Kompiliert die SQL-Anweisung in der Datenquelle vor und bindet die Visual FoxPro-Parameter. Dies bedeutet, daß die aktuellen Parameterausdrücke für alle Parameter in der SQL-Anweisung gespeichert werden. | |
SQLCOMMIT( ) | Fordert die Übergabe einer Transaktion an. | |
SQLROLLBACK( ) | Fordert das Zurücksetzen einer Transaktion an. | |
Datenquelleninformationen | SQLCOLUMNS( ) | Speichert eine Liste mit Spaltennamen und zugehörigen Informationen in einem Cursor. Gibt 1 bei erfolgreicher Ausführung der Funktion zurück oder 0, wenn die Ausführung noch andauert. |
SQLTABLES( ) | Speichert die Namen von Tabellen der Datenquelle in einem Cursor. Gibt 1 bei erfolgreicher Ausführung der Funktion zurück oder 0, wenn die Ausführung noch andauert. | |
Verschiedene Steuerungsmöglichkeiten | SQLGETPROP( ) | Erhält eine Verbindungseigenschaft von einer aktiven Verbindung. |
SQLSETPROP( ) | Legt eine Eigenschaft einer aktiven Verbindung fest. |
SPT-Kommandos ausführen
Bevor man über SQL Pass-Through auf den Server zugreifen kann, muß man eine Connection aktivieren. Dies geschieht entweder über eine benannte Verbindung, die in der VFP-Datenbank gespeichert ist (siehe Remote Views) oder direkt über die ODBC Datenquelle. Die Verbindung wird mit der SQLCONNECT()-Funktion geöffnet.
lnH = SQLCONNECT("conn1")
Wir verwenden hier die benannte Verbindung conn1 aus unserem Beispiel. SQLCONNECT() gibt bei Erfolg ein Handle auf die geöffnete Connection zurück, das bei der Ausführung weiterer Kommandos genutzt werden muß. Nun kann man zum Beispiel eine Abfrage ausführen:
SQLEXEC(lnH, "SELECT * FROM kunden", "ckunde")
In diesem Fall soll der Inhalt unserer Kundentabelle im Cursor ckunde zurückgegeben werden. Nach Ausführung der Kommandos sollte die Verbindung wieder mit getrennt werden:
SQLDISCONNECT(lnH)
Remote Views sind eine sehr effiziente und einfache Möglichkeit, mit Client/Server Datenbanken zu kommunizieren. Manchmal allerdings braucht man den direkten Zugriff auf die Datenbank, zum Beispiel zum generieren künstlicher Schlüssel oder zum Ausführen von Transaktionen. Dann hat man mit SQL Pass-Through ein flexibles Werkzeug an der Hand, um die gewünschten Zugriffe auszuführen.
Ein kleiner Wehrmutstropfen bleibt doch noch bei der Benutzung von SPT. Dadurch, daß es sich hierbei um ein spezifisches Werkzeug für den Client/Server Zugriff handelt, kann man ein Anwendungsprogramm bei seiner Benutzung nicht ohne weiteres auf unterschiedlichsten Datenbanken laufen lassen (also auch nicht auf einer lokalen VFP-Datenbank). Deshalb ist es nicht empfehlenswert, SQL Pass-Through direkt im Programm zu codieren. Vielmehr sollte man SQL Wrapper-Methoden benutzen, die die gewünschte Datenbasis erkennen und den Befehl entsprechend generieren können.
Dies war ein recht großzügiger Überblick über die Möglichkeiten von Views und remote Zugriffen. Wenn Sie weitergehende Informationen zu SQL Pass-Through benötigen, besuche Sie die entsprechenden Sessions. Zum Thema SQL-Wrapper können Sie Kontakt mit den Tool-Herstellern aufnehmen, die diese anbieten. Einige Hersteller bieten auch die gesamte Steuerung von remote- und lokalen Zugriffen, was Ihnen viele graue Haare sparen dürfte.....
Für Fragen stehe ich Ihnen jederzeit unter Mengel@indisoft-gmbh.de
zur Verfügung. Sie erreichen mich auch auf unserer Website www.indisoft-gmbh.de.