Programmieren mit dBASE PLUS: Klasse Rowset

Aus Wikibooks


Die Daten, die aus einer SQL-Anweisung in einem Query-Objekt resultieren.

Syntax[Bearbeiten]

Diese Objekte werden automatisch von der Abfrage erzeugt.

spezielle Eigenschaften[Bearbeiten]

Die folgenden Tabellen enthalten die speziellen Eigenschaften und Methoden der Klasse Rowset
Eigenschaft Vorgabe Beschreibung
autoEdit true Legt fest, ob sich der Datensatzbereich per Vorgabe im Bearbeitungsmodus befindet oder ob hierzu beginEdit( ) aufgerufen werden muß.
autoNullFields true Gibt an, ob bei der Erstellung von neuen Datensätzen leere Felder mit Nullwerten gefüllt werden.
baseClassName ROWSET Kennzeichnet das Objekt als Instanz der Klasse Rowset.
className ROWSET Kennzeichnet das Objekt als Instanz der abgeleiteten benutzerdefinierten Klasse. Wenn keine benutzerdefinierte Klasse existiert, gilt die Voreinstellung von baseClassName.
codePage 0 Gibt eine Zahl zurück, die auf die aktuelle Code Seite verweißt, die mit der Tabelle verbunden ist.
endOfSet Gibt an, ob der Datensatzcursor auf eines der beiden Enden des Datensatzbereichs zeigt.
exactMatch true Whether rowset searches use a partial string match or an exact string match.
fields Ein Array der Feldobjekte in einem Datensatz.
filter Leerer String Filter-SQL-Ausdruck
filterOptions Überprüfung von Länge und Schreibweise Legt fest, wie der Filterausdruck angewendet werden soll.
handle BDE-Cusor-Handle.
indexName Leerer String Das Tag des aktiven Index.
languageDriver Leerer String Gibt eine Zeichenkette zurück, die den Namen des Sprachtreibers, der momentan verwendet wird, anzeigt.
live true Gibt an, ob die Daten verändert werden können.
locateOptions Überprüfung von Länge und Schreibweise Legt fest, wie der Ausdruck angewendet werden soll, der die Positionierung bestimmt.
masterChild Begrenzt In einem master-detail Link, wird festgelegt, ob das Rowset der Child-Tabelle eingeschränkt ist, oder nicht.
masterFields Leerer String Feldliste für die Haupt-/Detail-Verknüpfung.
masterRowset Null Verweis auf das übergeordnete Rowset-Objekt.
modified false Zeigt an, ob der Datensatz verändert wurde.
name Leerer String Der Name eines benutzerdefinierten Datenobjektes
navigateByMaster false Whether to syncronize movement in a linked-detail rowset to match that of it's master.
navigateMaster false Whether to move the row position in a master rowset when a linked-detail rowset reaches endofSet.
notifyControls true Legt fest, ob über dataLink verknüpfte Steuerungselemente automatisch aktualisiert werden sollen.
parent Null Das Query-Objekt, das das Rowset-Objekt enthält.
state 0 (Geschlossen) Ziffernwert, der den Modus angibt, in dem sich der Datensatzbereich befindet.
tableDriver Leerer String Gibt einen Zeichenstring zurück, der den Namen des aktuellen Treibers anzeigt, der verwendet wird, um Zugang zu einer Tabelle zu bekommen.
tableLevel 0 Gibt einen Integer-Wert zurück, der die Version der aktuellen lokalen Tabelle angibt.
tableName Leerer String Gibt einen Zeichenkette zurück, der den Namen der Tabelle angibt, auf den das aktuelle Rowset aufbaut.
tempTable false Gibt einen logischen Wert (True/False) zurück, wenn die aktuelle Tabelle eine temporäre Tabelle ist.

spezielle Events[Bearbeiten]

Event Parameter Beschreibung
canAbandon Wird beim Aufruf von abandon( ) ausgelöst. Der Rückgabewert bestimmt, ob ein Datensatz verworfen werden kann oder nicht.
canAppend Wird beim Aufruf von beginAppend( ) ausgelöst. Der Rückgabewert gibt an, ob der Anfügemodus aktiviert werden kann oder nicht.
canDelete Wird beim Aufruf von delete( ) ausgelöst. Der Rückgabewert gibt an, ob Löschen möglich ist oder nicht.
canEdit Wird beim Aufruf von beginEdit( ) ausgelöst. Der Rückgabewert gibt an, ob in den Bearbeitungsmodus gewechselt werden kann.
canGetRow Wird beim Versuch ausgelöst, einen Datensatz zu lesen. Der Rückgabewert wirkt als zusätzlicher Filter.
canNavigate <Arbeitsbereich AusdruckN> Wird beim Versuch ausgelöst, Bewegungen im Arbeitsbereich durchzuführen. Der Rückgabewert bestimmt, ob der aktuelle Datensatz verlassen werden kann.
canSave Wird beim Aufruf von save( ) ausgelöst. Der Rückgabewert gibt an, ob ein Datensatz gespeichert werden darf oder nicht.
onAbandon Wird nach der erfolgreichen Ausführung von abandon( ) aufgerufen.
onAppend Wird nach der erfolgreichen Ausführung von beginAppend( ) aufgerufen.
onDelete Wird nach der erfolgreichen Ausführung von delete( ) aufgerufen.
onEdit Wird nach der erfolgreichen Ausführung von beginEdit( ) aufgerufen.
onNavigate <Methode AusdruckN>, <Datensätze AusdruckN> Wird nach einer Bewegung im Datensatzbereich aufgerufen.
onSave Wird nach der erfolgreichen Ausführung von save( ) aufgerufen.

spezielle Funktionen/Methoden[Bearbeiten]

Methode Parameter Beschreibung
abandon( )   Anstehende (noch nicht ausgeführte) Änderungen am aktuellen Datensatz werden verworfen.
applyFilter( )   Aktiviert die Filtereinstellungen, wenn sich der Datensatzbereich im Filtermodus befindet.
applyLocate( ) [<SuchausdruckZ>] Findet den ersten Datensatz, der das angegebene Kriterium erfüllt.
atFirst( )   Liefert True, wenn der aktuelle Datensatz der erste Datensatz des Datensatzbereichs ist.
atLast( )   Liefert True, wenn der aktuelle Datensatz der letzte Datensatz des Datensatzbereichs ist.
beginAppend( )   Das Anfügen eines neuen Datensatzes wird gestartet.
beginEdit( )   Aktiviert für den Datensatzbereich den Bearbeitungsmodus, so daß Felder geändert werden können.
beginFilter( )   Aktiviert für den Datensatzbereich den Filtermodus, so daß Filterkriterien eingegeben werden können.
beginLocate( )   Aktiviert für den Datensatzbereich den Suchmodus, so daß Kriterien eingegeben werden können.
bookmark( )   Gibt die Positionsmarke für den aktuellen Datensatz zurück.
bookmarksEqual( ) <PosMarke 1> [,<PosMarke 2>] Vergleicht zwei Positionsmarken oder eine Positionsmarke mit dem aktuellen Datensatz, um zu prüfen, ob sie sich auf denselben Datensatz beziehen.
clearFilter( )   Deaktiviert den mit applyFilter( ) definierten Filter und setzt die Eigenschaft filter zurück.
clearRange( )   Deaktiviert Einschränkungen, die durch setRange( ) erstellt wurden.
count( )   Gibt die Anzahl der Sätze in einem Datensatzbereich zurück. Filter werden dabei berücksichtigt.
delete( )   Löscht den aktuellen Datensatz.
findKey( ) <Schlüsselausdruck> Sucht den Datensatz, der dem Schlüsselwert exakt entspricht.
findKeyNearest( ) <Schlüsselausdruck> Sucht den Datensatz, der dem Schlüsselwert am ehesten entspricht.
first( )   Positioniert den Datensatzzeiger auf den ersten Datensatz eines Bereichs.
flush( )   Schreibt den Inhalt des Datensatzbereichspuffers auf die Festplatte.
goto( ) <PosMarke> Positioniert den Datensatzcursor auf den angegebenen Satz.
isRowLocked( )   Determines if the current row, in the current session, is locked.
isSetLocked( )   Determines if the current rowset, in the current session, is locked.
last( )   Positioniert den Datensatzcursor auf den letzten Datensatz eines Bereichs.
locateNext( ) [<Datensätze AusdruckN>] Sucht weitere Datensätze, die das Kriterium erfüllen.
lockRow( )   Sperrt den aktuellen Datensatz.
lockSet( )   Sperrt den gesamten Datensatzbereich.
next( ) [<Datensätze AusdruckN>] Positioniert auf benachbarte Datensätze.
refresh( )   Aktualisiert den gesamten Datensatzbereich.
refreshControls( )   Aktualisiert über dataLink verknüpfte Steuerungselemente.
refreshRow( )   Aktualisiert nur den aktuellen Datensatz.
rowCount( )   Liefert, falls bekannt, die relative Anzahl der Datensätze im Datensatzbereich.
rowNo( )   Liefert, falls bekannt, die relative Nummer eines Datensatzes im Datensatzbereich.
save( )   Speichert den aktuellen Datensatz.
setRange( ) <key exp> oder
<startKey exp> | null,
<endKey exp> | null
Schränkt das rowset auf diejenigen Reihen ein, deren Schlüsselfeldwert innerhalb eines Bereiches fällt.
unlock( )   Hebt die von lockRow( ) oder lockSet( ) gesetzte Sperre wieder auf.

Beschreibung[Bearbeiten]

Ein Rowset-Objekt repräsentiert eine bestimmte Menge von Datensätzen (Tabellenzeilen), die das Ergebnis einer Abfrage darstellen. Das Objekt verwaltet einen Cursor, der auf einen der Datensätze im Bereich zeigt. Dieser Datensatz wird als der aktuelle bezeichnet. Außerdem wird ein Puffer für den Inhalt eines Datensatzes eingerichtet. Unter Umständen kann der Cursor auf eine Position außerhalb des Bereichs zeigen, d.h., er befindet sich vor der ersten oder hinter der letzten Zeile. Man sagt dann, der Cursor zeigt auf eines der Enden des Bereichs. Jeder Datensatz kann Felder aus nur einer oder aus mehreren Tabellen enthalten. Diese Felder werden von einem Array aus Field-Objekten repräsentiert, das wiederum durch die Eigenschaft fields des Datensatzbereichs repräsentiert wird. Betrachten wir folgende einfache Abfrage:

select * from CUSTOMER

Hierbei werden alle Felder einer einzigen Tabelle ausgewählt, ohne daß dabei irgendwelche Bedingungen zu berücksichtigen sind. Der Datensatzbereich enthält also alle Daten der Tabelle. Indem der Cursor von einer Zeile zur nächsten bewegt wird, kann auf die einzelnen Felder des jeweiligen Datensatzes zugegriffen werden.

Ein Query-Objekt besitzt immer eine Eigenschaft rowset. Allerdings enthält dieser Datensatzbereich erst dann Felder und ist erst dann geöffnet und verwendbar, wenn die Abfrage erfolgreich ausgeführt wurde. Wenn die Eigenschaft active des Query-Objekts auf True gesetzt wird, wird die Abfrage geöffnet, und die in der Eigenschaft sql enthaltenen SQL-Anweisungen werden ausgeführt. Wenn eine SQL-Anweisung fehlschlägt, weil sie beispielsweise einen Tippfehler enthält oder die angegebene Tabelle nicht gefunden werden kann, wird ein Fehler generiert, und die Eigenschaft active behält den Wert False. Wenn die SQL-Anweisung zwar ausgeführt wird, aber keine Datensätze zurückliefert, erhält sowohl die Eigenschaft active als auch die Eigenschaft endOfSet des Rowset-Objekts den Wert True. Andernfalls ist endOfSet False, und der Datensatzbereich enthält die resultierenden Datensätze.

Nachdem der Datensatzbereich geöffnet wurde, können Sie die folgenden Aktionen ausführen:

  • Navigation innerhalb des Datensatzbereichs, das heißt Bewegung des Datensatzcursors.
  • Datensätze mit Filtern suchen.
  • Datensätze hinzufügen, ändern und löschen.
  • Einzelne Datensätze oder den gesamten Bereich explizit sperren.
  • Informationen über den Datensatzbereich abrufen, etwa über die aktuelle Position des Datensatzcursors.

Die einzelnen Field-Objekte im fields-Array eines Datensatzbereichs können über dataLink mit den Steuerelementen eines Formulars verknüpft werden. Während der Cursor von einer Zeile zur nächsten bewegt wird, werden die Steuerungselemente mit den jeweils aktuellen Werten versorgt. Voraussetzung ist, daß die Eigenschaft notifyControls auf True gesetzt ist. Sobald die in den Steuerungselementen angezeigten Werte verändert werden, ändert sich auch die value-Eigenschaft der über dataLinked verknüpften Field-Objekte. Die value-Eigenschaft des Field-Objekts kann auch direkt geändert werden. Sämtliche Werte werden dabei im Datensatzpuffer verwaltet.

Rowset-Objekte unterstützen das Prinzip der Haupt-/Detail-Verknüpfung. Bewegungen und Aktualisierungen im übergeordneten Datensatzbereich, dem Master-Bereich, ändern die Zusammensetzung des untergeordneten Datensatzbereichs, des Detailbereichs. Der Detail-Datensatzbereich entsteht dadurch, daß die gültigen Schlüsselwerte eines bestehenden Index im Detailbereich geändert werden. Die Eigenschaften masterRowset und masterFields werden hier gesetzt. Somit kann ein einziger Master-Datensatzbereich eine beliebige Anzahl von Detail-Datensatzbereichen steuern.

Wenn eine Abfrage geöffnet wird, befindet sich der zugehörige Datensatzbereich im Tabellenlayout-Modus. Standardmäßig hat die autoEdit-Eigenschaft eines Rowset-Objekts den Wert True; das bedeutet, daß seine Felder mit Hilfe von datenverknüpften Steuerelementen bearbeitet werden können. Erfolgt nun in einem mit dataLink verknüpften Steuerelement ein destruktiver Tastendruck, wird automatisch versucht, für den Datensatzbereich den Bearbeitungsmodus zu aktivieren. Wird autoEdit dagegen auf False gesetzt, kann der Datensatzbereich nur gelesen werden; um in den Bearbeitungsmodus zu wechseln, muß erst die Methode beginEdit( ) aufgerufen werden. autoEdit hat keine Auswirkungen auf die Bearbeitung der value-Eigenschaft eines Feldes; eine solche ist immer möglich.

Die Eigenschaft modified eines Rowset-Objekts zeigt an, ob am aktuellen Datensatz Änderungen vorgenommen wurden. Änderungen am Datensatzpuffer werden erst dann gespeichert, wenn die Methode save( ) aufgerufen wird oder eine implizite Speicherung veranlaßt wurde. Eine solche implizite Speicherung kann durch folgende Aktionen ausgelöst werden:

In all diesen Fällen, sogar bei einem expliziten Aufruf von save( ), wird kein Versuch einer Datenspeicherung unternommen, solange die Eigenschaft modified des Rowset-Objekts den Wert False hat. Aufgrund dieser Architektur muß im canSave-Event-Handler nur ein einziges Mal Datenvalidierungscode definiert werden, der wirklich nur im Bedarfsfall aufgerufen wird.

Zusätzlich zum normalen Datenzugriff im Tabellenlayout- oder Bearbeitungsmodus werden drei weitere Modi unterstützt: Anfügen, Filtern und Suchen, die jeweils mit beginAppend( ), beginFilter( ) und beginLocate( ) aktiviert werden. Sobald in einen dieser drei Modi gewechselt wird, löst sich die Zuordnung des Datensatzpuffers zum aktuellen Datensatz, und der Puffer wird geleert. Somit können Feldwerte entweder von Steuerungselementen übernommen werden, die mit dataLink verknüpft sind, oder direkt der value-Eigenschaft zugeordnet werden. Im Anfügemodus werden diese neuen Werte als neuer Datensatz gespeichert, wenn der Datensatzpuffer auf die Festplatte geschrieben wird. Im Filtermodus bewirkt die Methode applyFilter( ), daß alle nicht leeren Felder als Kriterium für die Selektion von Sätzen verwendet werden, wobei nur die Übereinstimmungen angezeigt werden. Im Suchmodus gilt dies für applyLocate( ) analog. Alle drei Modi werden deaktiviert, sobald mit den Feldwerten gearbeitet wird. Ein Aufruf der Methode abandon( ) bewirkt ebenfalls, daß der Datensatzbereich zurück in den Browse- oder Edit-Modus versetzt wird, ohne die Werte zu verwenden.

Filter- und Suchfunktionen lassen sich in den jeweiligen Modi recht einfach implementieren. Anstatt den Filtermodus zu benutzen, können Sie der Eigenschaft filter des Datensatzbereichs auch direkt einen SQL-Ausdruck zuweisen. Das Event canGetRow des Rowset-Objekts filtert Datensätze nach Maßgabe eines dBL-Codes, nicht nur einer SQL-Anweisung, und kann den Filtermodus ersetzen bzw. ergänzen. Die Methode applyLocate( ) kann auch verwendet werden, ohne vorher den Suchmodus zu aktivieren, indem eine SQL-Anweisung zum Auffinden des ersten Datensatzes übergeben wird, für den der Ausdruck zu True ausgewertet wird.

Jedes Kriterium zur Datensatzauswahl wird aktiv unterstützt, ob es sich dabei um eine WHERE-Klausel in der SQL-SELECT-Anweisung handelt, um die Definition eines Indexbereichs durch eine Haupt-/Detail-Verknüpfung oder um einen Filter. Mit applyLocate( ) werden nur Datensätze gefunden, die dem Kriterium entsprechen. Beim Anfügen eines neuen Satzes oder beim Ändern eines vorhandenen kann es sein, daß Filterbedingungen nicht mehr erfüllt werden. Der betreffende Datensatz wird dann nicht mehr als Element des Bereichs angesehen, und der Datensatzcursor wird zur nächsten Zeile bzw. zum Bereichsende bewegt, wenn keine weiteren Übereinstimmungen mehr gefunden werden. Um den ausgeschlossenen Datensatz wieder sichtbar zu machen, müssen Sie das Auswahlkriterium entsprechend ändern.

Die Unterstützung von Datensatz- und Datensatzbereichssperren richtet sich nach dem Tabellentyp. Die Standardtabellen (DBF und DB) unterstützen komplett ein Sperrschema, das dem einiger SQL-Server entspricht. Bei Servern, die keine echten Sperren unterstützen, emuliert die Borland Database Engine ein optimistisches Sperrschema. Für jede Anforderung einer Sperre wird Erfolg vorausgesetzt. Wenn später der tatsächliche Versuch der Datenänderung erfolgt, kommt es zu einem Fehler, wenn die Daten seit dem Sperrversuch geändert wurden.

Jeder Versuch, einen Datensatz zu ändern, führt zu einem automatischen Sperrversuch. Auslöser kann zum Beispiel die Eingabe von Zeichen in ein über dataLink verknüpftes Steuerungselement sein. Ist der Datensatz bereits gesperrt, wird der Versuch so oft wiederholt, wie in der Eigenschaft lockRetryCount der Arbeitssitzung angegeben ist. Hat die automatische Sperre Erfolg, bleibt diese bestehen, bis eine Bewegung aus dem gesperrten Datensatz heraus erfolgt oder der Datensatz gespeichert oder verworfen wird. Die Sperrung wird dann automatisch aufgehoben.

Beispiele[Bearbeiten]