[ 1 ] [ 2 ] [ 3 ] [ 4 ] [ 5 ] [ 6 ] [ 7 ] [ 8 ] [ 9 ]

Die Connection Definition im DBC

Wird eine Remote View erstellt, so muss man zunächst eine Connection aus dem DBC auswählen. Doch Achtung: Diese "DBC Connection" ist nur die Definition, wie auf den SQL Server zugegriffen werden muss und hat mit den effektiven Connections, welche später durch das Öffnen von verschiedenen Remote Views verwendet werden, nichts zu tun. Die Connection Definition wird im VFP Database Container (DBC) abgespeichert.

Die im DBC zu definierende Connection beinhaltet folgende Informationen:

Um zur Laufzeit die Connection den aktuellen Bedingungen beim Kunden am besten anpassen zu können, empfiehlt es sich, mit der Option "Connection string" zu arbeiten. Ein ausführlicher Connection String beinhaltet folgendes:

    DSN=Fibu;SERVER=(local);UID=;APP=Microsoft® Visual FoxPro®;WSID=HINOTE2000;DATABASE=Fibu;AutoTranslate= No;Trusted_Connection=Yes;UseProc
    ForPrepare=0;QuotedId=No;AnsiNPW=No

Wobei die einzelnen Optionen im Wesentlichen denjenigen Einstellungen entsprechen, welche auch beim Definieren eines ODBC-DSN Eintrages vorkommen.

TIP:Um obigen Connection String zu erhalten, kann man auf "Verify Connection" klicken. Es wird hierbei alles aus der entsprechenden DSN Definition gelesen und entsprechend in den Connection String aufgenommen.

WICHTIG: Um beim Einsatz Ihres Programmes beim Kunden keine Probleme zu haben, müssen Sie unbedingt sicherstellen, dass keine umgebungsspezifischen Einstellungen im Connection String vorkommen. Am sichersten ist es, wenn Sie hierzu nur den DSN=DsnName Eintrag, wie in obigem Bild dargestellt, verwenden. Das gibt Ihnen die Möglichkeit, beim Kunden vor Ort die Einstellungen in der DSN Definition, d.h. beim Definieren der ODBC Verbindung, vorzunehmen. Um zur Laufzeit den Connection String zu manipulieren, z.B. weil der Kunde mit einem anderen DSN Eintrag arbeiten muss, oder diesen zur Laufzeit ändern will, bietet VFP folgende Möglichkeit:

    dbsetprop("conFibu", "CONNECTION", "ConnectString", "dsn=" + alltrim(m.gs_dsn))

Das ist sehr praktisch und bietet sich an, um System- oder manchmal sogar Benutzerspezifische Einstellungen zur Laufzeit entsprechend anzupassen.

Denken Sie aber immer daran, wenn Sie z.B. systemspezifische Einstellungen zur Laufzeit einstellbar machen, dass Sie diese dann auf ALLEN Arbeitsstationen entsprechend sicherstellen müssen. So muss z.B. ein definierter DSN Eintrag unbedingt bei allen Benutzern vorhanden sein. Das ist mitunter einer der Hauptgründe, weshalb sich eine 3-Tier Architektur gegenüber einer 2-Tier Architektur immer mehr durchsetzt. Bei einer 3-Tier Architektur gibt es nur einen Ort, wo Datenbankverbindungen hergestellt werden, diese werden nicht mehr von allen Clients aus vorgenommen. Das vereinfacht natürlich die Administration dbzgl. wesentlich und erhöht auch die Betriebssicherheit entsprechend.

Connections von Remote Views

Beim Erstellen einer Remote View muss immer zuerst eine im DBC vorhandene Connection ausgewählt werden.

Wird die Remote View anschliessend erstellt, ist in der View Definition die in obigem Dialog ausgewählte Connection Definition fest abgespeichert. Wird die Remote View erstellt, muss im Menu "Query"

die Option "Advanced Options…" angewählt werden, um folgende Einstellungen im "Advanced Options" Dialog vornehmen zu können:

Die Checkbox "Share Connection" ist mitunter eine der wichtigsten überhaupt. Nur wenn diese angeklickt ist, kann sichergestellt werden, dass eine neu geöffnete Remote View versucht, eine bereits vorhandene Connection einer zuvor durch eine andere Remote View geöffnete Connection, zu nutzen.

ACHTUNG: Eine manuell zuvor geöffnete Connection wird nie hierfür in Betracht gezogen! Das ist auch gut so, denn VFP kann ja nicht wissen, was mit dieser "fremden" Connection alles bewerkstelligt wurde oder noch wird. Vielleicht wurde damit ja bereits ein SQL Prepare String an den Server gesendet oder es läuft bereits eine Transaktion darauf.

Was VFP aber kann, ist das Verwenden einer Connection, welche VFP selbst für das Erstellen einer anderen Remote View bereits eröffnet hat. Das und nur das bedeutet "Share Connection".

Daraus ergibt sich folgende Schlussfolgerung, um bei deiner Anwendung bzgl. der verwendeten Connections zum Datenbankserver eine möglichst hohe Performance zu erziehlen:

Perfomance Richtlinien im Zusammenhang mit Connections

Es ergeben sich folgende Performance Richtlinien, welche im Zusammenhang mit offenen Connections vom Client zum Datenbank Server stehen:

  • Für jeden Benutzer und Anwendung ist eine Remote View zu öffnen, welche am besten gleich nach dem Start der Applikation geöffnet wird, und während der gesamten Laufzeit der Applikation nicht mehr geschlossen wird. Alle Remote Views, verwenden die Option "Share Connection", wie oben beschrieben und verwenden somit ein und dieselbe Connection. Dies auch über verschiedene Forms mit "private datasession".
  • Es werden für alle SPT Anweisungen maximal eine separate Connection verwendet. Evtl. kann sogar dieslbe "shared" Connection, welche bereits für die Remote Views verwendet wird, eingesetzt werden. Um diese zu ermitteln, kann mit der Anweisung lnconnection = CURSORGETPROP("ConnectHandle") die Connection Nummer ermittelt werden. (Diese sollte 1 sein, wenn die Connection ganz zu Beginn durch das Öffnen einer ersten Remote View erstellt wurde).
  • Es muss für jede SQL Prepare Query eine zusätzliche Connection verwendet werden. Sendet man SQL Prepare Strings an den SQL Server, so muss hierfür die Connction exklusiv verwendet werden! In diesem Fall gibt es keine andere Möglichkeit, als eine neue Connection zu verwenden. SQL Prepares lohnen sich demzufolge wirklich nur, wenn sehr häufig hintereinander dieselbe Anweisung abgesetzt wird

Aus diesen Richtlinien ergibt sich, dass man sich bei den Remote Views eigentlich keine besonderen Gedanken mehr zu machen braucht. Oder doch? Da wäre noch dieses eine kleine Detail…

Busy Connections

Eine Connection kann auch einmal "busy" (also beschäftigt) sein! Dem muss natürlich vorgebeugt werden, ansonsten der Ansatz, eine einzige Connection für alle Remote Views zu verwenden, natürlich zum Scheitern verurteilt ist. Deshalb ist darauf zu achten, wie man bei den oben gezeigten "Advanced Options" der Remote View Definition die Einstellungen "Numer of Record to Fetch at a time", sowie "Maximum number of records to fetch" auf -1, d.h. alle, einstellt. Macht man nämlich den Fehler, und sagt, es sollen nur die ersten 100 Datensätze bezogen werden, die abgesetzte Query jedoch z.B. 101 Datensätze beinhalten würde, so würde die Connection "busy" bleiben, bis der 101ste Datensatz wirklich bezogen wird! Dieser Zustand ist alles andere als wünschenswert und führt auch noch zu anderen unangenehmen Situationen. So ist es z.B. auch nicht möglich, im Falle einer solchen "busy" Connection einen Datensatz in der View upzudaten oder einen neuen Datensatz über die View in der Server Datenbank anzulegen.

Man tut sehr gut daran, "busy" Connections gar nicht erst entstehen zu lassen. Sind Operationen asynchron durchzuführen, bietet sich sowieso eher der Ansatz über ADO und spezielle WITH EVENTS in VB bzw. der VFPCOM.DLL an.

Der VFX Connection Manager

Um diejenigen Connections, welche man bzgl. SPT und prepared SQL Queries manuell verwalten will oder muss, wäre es natürlich sehr nützlich, hätte man einen Connection Manager, der einem folgende Dinge abnehmen würde:

  • Erstellen einer neuen Connection
  • Holen einer freien Connection und nur falls nötig eine neue Connection erstellen
  • Übersicht über alle Connections in eigenem Connection Pool
  • Schliessen aller mit dem Manager erstellten Connections
  • Setzen und Lesen der Connection Parameter wie DBC Connaction name, DSN Name, User ID und Passwort
  • Eigene Garbage Collection mit Schliessen aller Connections bei Destroy des Objektes

Sie ahnen es natürlich bereits: VFX besitzt einen solchen Connection Manager und ich werde diese nützliche Klasse und deren Verwendung in der Session kurz vorstellen.

Remote Views vs. SPT

Wenn man eine Remote View definiert und mit "Share connection" darauf achtet, dass man nicht neue Connections verwendet, hat man eigentlich schon einen grossen Schritt in Richtung Performance Optimierung getan. Will man nun auch noch die letzten 10% Peformance Gewinn rausholen, kann es sich sogar lohnen, dass man zur Laufzeit aus den Remote Views SPT Anweisungen macht, da diese i.d.R. noch einen Tick schneller laufen, als die entsprechenden Remote Views.

Comboboxen und Pickfields, (u.U. sogar noch Grids), sind dbzgl. besonders dankbare Optimierungs Kandidaten.

In VFX haben wir dbzgl. die Möglichkeit geschaffen, bei Comboboxen, Pickfields und Grids statt die zur Designzeit definierten Remote Views, diese zur Laufzeit vollautomatisch in SPT Anweisungen "umzubauen" und so von der etwas rascheren Verarbeitungsgeschwindigkeit von SPT Anweisungen zu profitieren.

Es genügt hierbei im Wesentlichen, die entsprechende Property, namens lUseSPT auf .t. zu setzen. VFX nimmt dann intern den oben beschriebenen Connection Manager zu Hilfe, um eine freie Connection zu verwenden, um die SPT Anweisung erfolgreich absetzen zu können.

Erstellen von SPT Anweisungen aus Remote Views

Das VFX Framework erstellt aus den Remote View Definitionen die entsprechenden SPT Anweisungen, indem die Remote View gelesen wird und als SPT String abgesetzt wird.

Bei der CPickField Klasse kann man wie gewohnt je eine Remote View für das Picken (Property cTableName) sowie eine für die Validierung (Property CViewValid) definieren.

Durch das Setzen der Property lUseSpt werden diese beiden Remote Views zur Laufzeit in SPT Anweisungen (inkl. Parameters!) umgewandelt. Als VFX Entwickler braucht man sich hier um keine weiteren Details mehr zu kümmern.

Bei den Grids ist es zur Zeit so, dass diese Technik nur bei "Read Only" Grids funktioniert.

Bei den Comboboxen dient die Property cTableName dazu, den Namen des Cursors, welcher aus der SPT Anweisung für den Rowsource resultiert, festzuhalten.

Die Datenumgebung von Forms

Es ist einleuchtend, dass, je mehr Remote Views in einer Datenumgebung geöffnet werden, die Performance der Anwendung abnimmt. Das Form wird bei mehr Views in der Datenumgebung entsprechend länger zu laden haben. Selbst wenn Sie "NoDataonLoad" anwählen, d.h. dass beim Laden des Forms nur die Strukturen der Remote Views geladen werden müssen, so ist dies dennoch mit einem nicht zu unterschätzendem Overhead verbunden, müssen doch für alle Felder die entsprechenden Attribute vom Server bezogen werden und die Remote View der Struktur entsprechend aufgesetzt werden.

HINWEIS: Auch wenn Sie nicht mit SCX Dateien und Datenumgebungen operieren, sondern stattdessen direkt Ihre Formklassen instantiieren oder die Datenumgebung aus Ihrem SCX entfernt haben und im Load das Öffnen der Daten von Hand oder eine separate DE Klasse bewerkstelligen, gelten diese Ausführungen natürlich sinngemäss weiterhin.

In unserem Client/Server Ansatz im VFX Framework haben wir hierfür eine elegante Lösung gefunden. Wir können mit der Verwendung der Klasse CAskViewArgPgf mit beliebig vielen Remote Views arbeiten, haben jedoch in der Datenumgebung immer nur eine einzige "Platzhalter" Remote View. Erst zur Laufzeit wird die entsprechende View geöffnet und an Stelle der Platzhalter View verwendet. Eine wirklich elegante Lösung um mit sovielen Remote Views, wie nötig, arbeiten zu können, ohne die Performance in irgendeiner Weise negativ zu beeinflussen!

[ 1 ] [ 2 ] [ 3 ] [ 4 ] [ 5 ] [ 6 ] [ 7 ] [ 8 ] [ 9 ]