Entwickeln Sie ein Verständnis für Record-Sets
8
Web-Datenbank-Programmierung mit ActiveX-Daten-Objekten
Die Data-Access-Komponente ist ein Bestandteil der ASP, der es Ihnen ermöglicht, ein Interface zwischen dem Server und einer Datenbank aufzubauen. Diese Komponente ist Bestandteil von ASP, und benutzt ActiveX-Data-Objects (ADO), um Datenbank-Funktionalitäten bereitzustellen. Lassen Sie uns doch mal einen Blick auf Microsofts ADO-Objekt-Modell werfen (siehe Abbildung 8.1).
Abbildung 8.1: |
Wir wollen unser Augenmerk auf die drei »geschützten« Objekte Connection, Command und Recordset richten. Als geschützte Objekte bezeichnet man Objekte, auf die Sie direkt, ohne Unterstützung eines Interfaces zugreifen können. Innerhalb ADOs ist das Recordset-Objekt das wichtigste, alle anderen Objekte dienen der Unterstützung der Erstellung dieses Objekts. Es ist wichtig im Kopf zu behalten, daß ADO die Aufgabe hat, auf Daten zuzugreifen und diese zu manipulieren. Das Design und diverse Reportfunktionen werden HTML überlassen.
ADO ist ein Daten-Zugriffs-Modell. Sollten Sie mit Microsofts anderen Objekten (DAO oder RDO) vertraut sein, so werden Sie sich sicherlich schnell in ADO einarbeiten können. Aber auch wenn Sie ein Neuling in diesem Bereich sind, werden Sie sich schnell mit diesem Modell anfreunden können.
Was Sie tun sollen |
Was nicht | |
Zwingen Sie Ihre Web-Site nicht in die Knie, indem Sie den falschen Daten-Provider aussuchen. Obwohl Sie ADO und ODBC zu sämtlichen Daten-Providern verbinden können, existieren bestimmte Limitierungen. Die DOA-Engine von Microsoft Access ist nur bedingt für Enterprise-Lösungen geeignet. SQL-Server oder andere Third-Party-Produkte mit ODBC-Treibern stellen für dieses Anwendungsgebiet eine bessere Wahl dar, insbesondere für Applikationen großer Intranets. Wir wollen uns innerhalb dieses Buches auf Microsoft Access beziehen. |
In diesem Kapitel erfahren Sie alles, was Sie benötigen, um mit Datenbanken zu arbeiten und eine Vielzahl von Beispiel-Applikationen zu erstellen. Sie benötigen dafür eine der Dateien von der MCP-Web-Site mit der Bezeichnung guestbook.mdb. Erstellen Sie am besten ein neues Verzeichnis mit der Bezeichnung C:\Inetpub\database, und plazieren Sie die Datei an dieser Stelle.
Was Sie tun sollen |
Was nicht | |
Stellen Sie keine sicherheitsrelevanten Daten in ein Verzeichnis des Servers, auf das Read-Rechte bestehen, da diese Daten auf den Client-Rechner geladen und gelesen werden können. |
ODBC-(Open DataBase Connectivity)-Treiber gestatten Ihnen den Zugriff auf Systeme und Applikationen, die diesen Standard unterstützen. In der Sprache ADOs gesprochen, handelt es sich bei ODBC um einen Daten-Provider. ODBC können Sie über die Windows-Systemsteuerung kontrollieren und steuern. Um auf eine Datenbank zuzugreifen, müssen Sie ein DSN erstellen.
Es gibt verschiedene Arten von DSNs, die Sie zu erstellen in der Lage sind. Das User-DSN bezieht sich beispielsweise auf einen bestimmten Rechner oder User. Es ist sehr einfach, auf diese zuzugreifen, da es einen einfachen Namen hat. Es gibt jedoch keine Möglichkeit, einen User-DSN in eine Web-Applikation zu integrieren, da eine Vielzahl von Anwendern Zugriff auf diese Datei benötigen.
Anstelle des User-DSN sollten Sie vielmehr ein System-DSN oder Datei-DSN erstellen. Ein System-DSN ist für jeden Anwender und System-Service auf dem Server verfügbar. Auf ein System-DSN zuzugreifen ist sehr einfach, da diesem ein Name zugewiesen werden kann. Datei-DSNs sind nicht Rechner- oder User-spezifisch, so daß diese besser zu portieren sind als System-DSNs. In diesem Kapitel werden Sie ein System-DSN erstellen. Im Kapitel 11 werden Sie dann ein Datei-DSN erstellen.
ODBC 3.0 beinhaltet ein neues Feature mit der Bezeichnung »connection pooling«, das per Voreinstellung ausgeschaltet ist. Sie müssen das Service Pack 2 für NT Server 4 installiert haben, um das Connection Pooling zu benutzen. Es ist eine großartige Möglichkeit, die ODBC-Performance wesentlich zu erhöhen. Mehr Informationen finden Sie unter Microsofts Active-Server-Pages-Roadmap-Dokumentation (http://your_server_name/iasdocs/aspdocs/ref/comp/compref_13.htm). |
Um ein System-DSN zu erstellen, müssen Sie Mitglied der Administrator-Group sein. Öffnen Sie die Windows-Systemsteuerung, und führen Sie einen Doppelklick auf das Symbol ODBC32 aus, um das entsprechende Applet zu starten. Klicken Sie auf die DSN-Registerkarte. Sollten Sie alle Beispiele installiert haben, die mit ASP ausgeliefert werden, so haben Sie zwei System-DSN-Einträge, so daß das ADO in der Lage ist, Microsoft-Access-Daten abzuspeichern (siehe Abbildung 8.2).
ODBC32 wird mit Treibern für Microsoft Access und SQL-Server ausgeliefert. Sollten Sie andere Treiber benötigen, kontaktieren Sie bitte Ihren Händler, oder statten Sie der Microsoft Web-Site einen Besuch ab (Knowledge Base-Artikel Q159674).
Abbildung 8.2: |
Um ein neues DSN hinzuzufügen, führen Sie bitte folgende Schritte durch:
1. Klicken Sie auf die Schaltfläche Add (siehe Abbildung 8.2).
2. Wählen Sie den Microsoft Access Driver (*.mdb) aus der Liste der installierten Treiber.
3. Klicken Sie auf Finish.
4. Geben Sie jetzt den DSN-Namen guestbook ein. Dies ist der Name, der gemeinsam mit dem Objekt Connection benutzt wird. Den Namen können Sie frei wählen, er sollte jedoch beschreibende Funktionen übernehmen.
5. Geben Sie die optionale Beschreibung ein.
6. Wählen Sie in der Database-Box die Schaltfläche Select.
7. Klicken Sie auf die Datei guestbook.mdb.
8. Klicken Sie abschließend auf OK.
Abbildung 8.3 zeigt, wie die eingegebenen Informationen nach der entsprechenden Eingabe aussehen.
Abbildung 8.3: |
Was Sie tun sollen |
Was nicht | |
Sie haben die Möglichkeit zu bestimmen, wie viele Datenbanken innerhalb der Abbildung 8.3 vorgehalten werden können. Löschen oder fügen Sie Einträge hinzu, so wird sich die Größe der Datenbank entsprechend verändern. |
Klicken Sie auf die Schaltfläche Advanced. Von hier aus haben Sie die Möglichkeit, den User-Namen und ein Paßwort für den Zugriff auf die entsprechende Datei zu spezifizieren. Damit vermeiden Sie den mißbräuchlichen Gebrauch Ihrer Datenbank-Datei. An dieser Stelle gibt es noch weitere Optionen, die es Ihnen gestatten, mehr Kontrolle darüber zu erlangen, wie ein Zugriff auf Ihre Datenbank stattfindet. Für die meisten Applikationen genügt es jedoch, wenn Sie an dieser Stelle alles beim alten belassen. Klicken Sie auf OK, um zu dem in Abbildung 8.3 abgebildeten Bildschirm zu gelangen.
Klicken Sie auf die Schaltfläche Options. An dieser Stelle haben Sie die Möglichkeit, die Treiber-Eigenschaften zu setzen. Der Page Timeout definiert die maximale Zeit (in Sekunden), in der eine Seite im Buffer bei Nichtbenutzung vorgehalten werden soll. Buffer Size definiert die Größe des Buffers, der zum Transfer der Informationen zu und von der Festplatte benutzt wird. Die Größe des Buffers sollte auf 512 und der Page Timeout auf 5 gesetzt werden. Diese Werte sollten für die meisten ASP-Applikationen ausreichen. Sollten Sie jedoch große Datenmengen transferieren, so müssen Sie die Buffer-Größe entsprechend erhöhen. Klicken Sie auf OK, um die System-DSN-Definitionen abzuschließen.
In Kapitel 11 erfahren Sie, wie Sie die Werte eines Datei-DSN modifizieren können. Schließen Sie das ODBC32-Applet.
Das aus Abbildung 8.1 ersichtliche ADO-Objekt-Modell zeigt Ihnen die Beziehungen zwischen dem Objekt Connection und den Objekten Command und Recordset. Obwohl die anderen Objekte unabhängig erstellt werden können, so sind sie dennoch nicht in der Lage, mit anderen Daten-Quellen ohne Zuhilfenahme des Connection-Objekts zu kommunizieren.
Das Connection-Objekt hat die Aufgabe, den entsprechenden Daten-Provider zu spezifizieren. Sie können dieses Objekt ebenfalls benutzen, um einfache Kommandos durchzuführen oder Report-Records auszugeben. Komplexere Operationen, wie beispielsweise Löschen oder das Modifizieren von Einträgen, können durch die Objekte Command und Recordset realisiert werden.
Eine Verbindung herstellen
Nun, da Sie ein System-DSN erstellt haben, können Sie sich zu diesem verbinden. Sie haben die Möglichkeit, eine Verbindung zum Gästebuch-DSN herzustellen, indem Sie das Listing 8.1 benutzen.
Listing 8.1: Verbinden Sie sich zum Gästebuch-DSN
1: set ConnObj = Server.CreateObject("ADODB.Connection")
2: ConnObj.ConnectionTimeout = timeinseconds
3: ConnObj.Open "guestbook"
4: ConnObj.CommandTimeOut = timeinseconds
Das Listing 8.1 ist sehr einfach zu verstehen. Nun, da Sie eine Verbindung geöffnet haben, sind Sie in der Lage, Befehle zu senden und Einträge, sogenannte Record-Sets, zu erstellen. Zeile 1 erstellt ein ADO-Verbindungsobjekt. ADO versucht, Objekte für Sie zu erstellen, sollten Sie dies vergessen haben. Bedenken Sie jedoch, daß Sie viel Prozessorzeit und mögliche Fehler vermeiden, wenn Sie die Objekte selbst kreieren.
Zeile 2 setzt die Eigenschaft ConnectionTimeOut. Diese Eigenschaft bestimmt die Zeit, die ADO wartet, bis eine Verbindung zum Daten-Provider hergestellt wurde. Der Default-Wert beträgt 15 Sekunden. ConnectionTimeOut wird gesetzt, bevor eine entsprechende Verbindung in der nächsten Zeile geöffnet wird.
Die Zeile 3 ist dafür verantwortlich, das Connection-Objekt zu öffnen. Nachdem die Verbindung geöffnet wurde, können Sie damit beginnen, Einträge zu erstellen und Befehle zu übermitteln.
Zeile 4 setzt die ComandTimeOut-Eigenschaft. Diese Eigenschaft definiert die maximale Zeitspanne in Sekunden, die ADO wartet, bis der Data-Provider seinen Befehl ausgeführt hat. Per Standard ist dafür ein Wert von 30 Sekunden definiert, der für die meisten Server-Operationen ausreichen sollte. Setzen Sie den Wert auf 0, so wartet ADO auf einen Befehl zur Verarbeitung.
Überlegungen zur Performance und zum Datenschutz
Vielleicht reizt es Sie, Befehle zu versenden, um Einträge zu erstellen - warten Sie damit noch ein wenig. Untersuchen Sie doch mal den folgenden Code:
1: <!--#include virtual="/ASPSAMP/SAMPLES/ADOVBS.INC"-->
2: set ConnObj = Server.CreateObject("ADODB.Connection")
3: ConnObj.Mode = adModeRead
4: ConnObj.Open "guestbook"
Den Typus des Zugriffs auf Daten definiert die Eigenschaft Mode in Zeile 3. In unserem Beispiel wurde die Verbindung als Read-only definiert - Versuche der Dateneingabe ergeben an dieser Stelle eine Fehlermeldung. Alle Einträge, die auf Basis dieser Verbindung erstellt wurden, sind ebenfalls Read-only. Befehle, die versuchen, einen Eintrag hinzuzufügen oder zu editieren, produzieren eine Fehlermeldung.
Da stellt sich Ihnen mit Sicherheit die Frage nach dem Zweck dieser Prozeduren. Hier die beiden Antworten:
Die Eigenschaft Mode in Zeile 3 muß gesetzt werden, bevor das Connection-Objekt in Zeile 4 geöffnet wird. Der verfügbaren Werte für Mode sind in Tabelle 8.1 aufgelistet.
Tabelle 8.1: Werte für Mode
Konstanten |
Beschreibung |
adModeUnknown |
Die Genehmigungen wurden nicht gesetzt bzw. können nicht festgestellt werden. |
adModeRead |
Die Read-only-Genehmigung. AddNew oder das Editieren schlägt fehl. |
adModeWrite |
Ist eine Write-only-Erlaubnis, die dazu benutzt wird, um Tabellen mit SQL-Statements zu versehen (INSERT INTO). |
adModeReadWrite |
Read/Write-Permissions. |
AdModeShareDenyRead |
Schützt vor der Öffnung einer Verbindung mit Read-Permissions. Dieser Weg der Verbindungsaufnahme schützt Ihre Veränderungen, bis Sie beendet und eine Verbindung beendet wurde. |
adModeShareDenyWrite |
Schützt vor der Öffnung einer Verbindung mit Write-Permissions. Diese Methode sichert, daß niemand Informationen verändern kann, auf die Sie gerade zugreifen. |
adModeShareExclusive |
Schützt vor der Öffnung einer Verbindung mit Read/Write-Permissions. Benutzen Sie diese Methode, um zu sichern, daß sich niemand einmischen kann oder Ihre Eingaben zu lesen oder zu editieren in der Lage ist, bis Sie die Verbindung geschlossen haben. |
adModeShareDenyNone |
Schützt vor dem Öffnen einer Verbindung mit irgendwelchen Rechten. |
ADO bezieht sich zu einigen seiner Eigenschaften in Form von Zahlen. IsolationLevel, LockType, CursorType und Mode sind allesamt Integer-Argumente. Anstelle der Integer-Argumente können Sie der Einfachheit halber ADO-Konstanten verwenden, wie Sie in Microsofts ADO-Include-Datei enthalten sind. |
Um die ADO-Konstanten aus Tabelle 8.1 zu nutzen, müssen Sie zu Beginn Ihrer .asp-Datei eine Datei aufrufen. Microsofts ADO-Verb-Datei können Sie wie folgt integrieren <!--#include virtual="/ASPSAMP/SAMPLES/ADOVBS.INC"--> (wie Zeile 1 im gezeigten Code). Ihr Pfad unterscheidet sich von diesem Beispiel, wenn Sie ASP an anderer Stelle installiert haben.
Ein anderer Aspekt, den Sie innerhalb Ihres Codes beachten sollten, ist Redundanz. Sollten Sie das Connection-Objekt benutzen, um einen Record-Set zu erstellen, den viele Anwender benötigen, so ist es notwendig, die Informationen im Application- oder Sessions-Objekt abzuspeichern. Einen neuen Eintrag mittels des Connection-Objekts für jeden Anwender anzulegen ist nicht effizient. Widerstehen Sie der Versuchung, das Connection-Objekt abzuspeichern, da die Verbindung die meiste Zeit inaktiv sein wird. Um die Performance ohne Hilfe des Connection-Objekts zu erhöhen, benutzen Sie bitte das Connection-Pooling, das wir bereits in einem früheren Kapitel besprochen haben.
Die Verwendung der Execute-Methode, um Daten zu erhalten und zu modifizieren
Was können Sie jetzt mit der Verbindung anfangen, die Sie erstellt haben, und was hat das Connect-Objekt damit zu tun? Sie können derzeit zwei Dinge damit tun: Sie sind in der Lage, Befehle zum Daten-Provider zu versenden, und Sie können Report-Informationen empfangen. Beide Tätigkeiten basieren auf der Execute-Methode. In diesem Kapitel sehen Sie, wie Befehle innerhalb einer Verbindung versendet werden.
Listing 8.2 zeigt die Anwendung der Execute-Methode im Detail mit der Möglichkeit, Ihren Namen einem Gästebuch hinzuzufügen. Dazu der folgende Code:
Listing 8.2: Ein Namenseintrag mit Addme.asp
1: <!--#include virtual="/ASPSAMP/SAMPLES/ADOVBS.INC"-->
2: <% set ConnObj = Server.CreateObject("ADODB.Connection")
3: ConnObj.Mode = adModeWrite
4: ConnObj.Open "driver = {Microsoft Access Driver (*.mdb)};dbq
5: Â= c:\Inetpub\databases\guestbook.mdb"
6: Line1 = "INSERT INTO tblguestbook (fname,lname,phone,"
7: Line2 = "email,homepage, dateadded) VALUES (ôyour first nameõ,"
8: Line3 = "ôyour last nameõ, ôyour phoneõ, ôyour emailõ,"
9: Line4 = "ôyour homepageõ,õ" & now() & "ô)"
10: CommandText = Line1 & Line2 & Line3 & Line4
11: ConnObj.Execute CommandText, RecordsAffected, adCmdText %>
12: <HTML>
13: <%=RecordsAffected%> record(s) were added sucessfully!
14: </HTML>
15: <%ConnObj.Close%>
Das erste, was Sie über die Datei addme.asp wissen sollten, ist der Aspekt, der sie ein wenig von den bisher kennengelernten Beispielen unterscheidet (Zeile 4). Wenn Sie eine Verbindung erstellen, so ist es erst einmal notwendig, einen Treiber und eine Datenbank zu definieren. Im Rahmen dieses Buches haben Sie zu einem früheren Zeitpunkt die Datei guestbook.mdb und den Microsoft-Access-Treiber mit dem Guestbook-DSN verbunden. Sie benutzen diesen DSN, um Ihr erstes Connection-Objekt zu öffnen. Dies sind alle Informationen, die Sie benötigen. Auf diese Weise haben Sie die Möglichkeit, Verbindungen zu erstellen, ohne daß Sie über administrative Rechte verfügen.
Die Zeilen 6 bis 9 werden benutzt, um SQL-Statements zu erstellen, und die Zeile 10, um alles miteinander zu kombinieren.
Was Sie tun sollen |
Was nicht | |
Besorgen Sie sich ein Buch über SQL. SQL ergänzt ADO in idealer Art und Weise und erweitert die Funktionen ADOs immens. Bestens geeignet ist »SQL in 21 Tagen« von Sams. |
Zeile 11 benutzt die Execute-Methode, um den Daten-Provider zur Verarbeitung eines bestimmten Kommandos zu veranlassen. Diese Methode verfügt über drei Argumente:
Tabelle 8.2: Verfügbare Optionen
Konstante |
CommandText-Typ |
adCmdText |
Darunter ist ein Text-SQL-Kommando zu verstehen, das vom Daten-Provider verarbeitet wird. |
adCmdTable |
CommandText bezieht sich auf eine gespeicherte Tabelle. |
adCmdStoredProc |
CommandText bezieht sich auf eine gespeicherte Prozedur. |
adCmdUnknown |
Dies ist der Default-Wert. |
Sie sollten jetzt keine Fragen mehr über den Code des letzten Kapitels haben, mit Ausnahme der letzten Zeile. Das Connection-Objekt in Zeile 15 schließt alle Arbeiten ab. Sie müssen das Connection-Objekt ebenfalls schließen, wenn Sie dessen Eigenschaften geändert haben.
Achten Sie darauf, daß die Verbindung innerhalb Ihres Codes nicht zu früh geschlossen wird, da dies unangenehme Nebeneffekte mit sich bringen könnte. Das Schließen der Verbindung setzt die Eigenschaft ActiveConnection aller Objekte auf null. Sämtliche Einträge, die in Beziehung mit der Verbindung stehen, werden ebenfalls geschlossen, so daß Sie sicher sein sollten, sämtliche Aufgaben erfüllt zu haben, bevor Sie die Methode Close aufrufen.
Stellen Sie sich vor, es gäbe einen Weg, Dinge zehnmal schneller zu erledigen als normalerweise. Transaktionen bieten Ihnen diese Möglichkeit. Dieser »Geschwindigkeitsrausch« resultiert aus der Tatsache, daß Befehle und Resultate im RAM anstelle auf der Festplatte gespeichert werden. Diese Methode hat jedoch auch eine Schattenseite, da ein Fehler während einer Transaktion die gesamte Arbeit zunichte macht. Transaktionen zu benutzen ist sehr einfach. Alles, was Sie tun, kann dank einer Transaktion wesentlich effektiver erledigt werden. Sie benötigen dazu lediglich drei einfache Methoden: BeginTrans signalisiert den Start der Datenverarbeitung im RAM. Ist dies geschehen, müssen Sie den Code auf Fehler hin überprüfen. Wurden keine Fehler gefunden, sorgt die CommitTrans-Methode für die Übertragung der Änderungen. Tritt ein Fehler auf, fordert Sie die RollbackTrans-Methode dazu auf, sämtliche Änderungen zu widerrufen. Das folgende Beispiel zeigt die prinzipielle Struktur einer Transaktion: ConnObj.BeginTrans |
Sollten Sie Listings aus diesem Buch eingeben, können sich sehr leicht Fehler einschleichen. Dies ist insofern »dramatisch«, da in einem solchen Fall nicht immer Fehlermitteilungen erscheinen. Es gibt zwar eine Vielzahl von Fehlern, die Applikationen generieren können, nachdem jedoch der HTML-Code zum Browser gesandt wurde, werden diese nicht immer korrekt angezeigt. |
ADO verfügt nur über geringe Möglichkeiten für eine Fehlerbehandlung. 90% aller Fehler werden Ihre Applikation generieren. Um weiterführende Information darüber zu erhalten, lesen Sie bitte in der Microsoft-Dokumentation zu ADO nach.
Dieses Objekt ist das Arbeitspferd innerhalb von ADO. Nahezu alles, was Sie in ADO erledigen, basiert auf diesem Record-Set. Record-Sets sind tabellarische Objekte, die Ihre Daten enthalten. Die Werte basieren auf Zeilen und Spalten. Eine tiefergehende Einführung in diese Materie erhalten Sie zu einem späteren Zeitpunkt dieses Kapitels.
Sollten Sie Microsoft Access installiert haben, können Sie sich mit der Datenbank und deren Design im Vorfeld vertraut machen. Insgesamt gibt es nur zwei Objekte in der Datenbank - eine Tabelle mit der Bezeichnung tblguestbook und einem Query mit Namen findme. Tabelle 8.3 zeigt den Aufbau von tblguestbook.
Tabelle 8.3: Die definierten Felder in tblguestbook
Feld |
Beschreibung |
Typ |
Größe |
no |
Besuchernummer |
Auto |
(long integer) |
fname |
Vorname |
Text |
50 |
lname |
Nachname |
Text |
50 |
phone |
Telefonnummer |
Text |
50 |
E-Mail-Adresse |
Text |
50 | |
homepage |
Homepage URL |
Text |
50 |
dateadded |
Besuchsdatum |
Date/time |
N/A |
Das Listing 8.3 (findme.asp) ist eine Erweiterung des Listings 8.2. Anstelle der Eingabe Ihres Namens sucht das Skript nach einem vorhandenen Datensatz. Die Applikation fordert Sie dazu auf, Ihren Namen einzugeben (siehe Abbildung 8.4) und gibt eine Besuchernummer aus (siehe Abbildung 8.5).
Listing 8.3: Finden Sie Ihren Eintrag findme.asp
1: <!--#include virtual="/ASPSAMP/SAMPLES/ADOVBS.INC"-->
2: <% set ConnObj = Server.CreateObject("ADODB.Connection")
3: Set RstObj = Server.CreateObject("ADODB.Recordset")
4: RstObj.CursorType = adOpenForwardOnly
5: RstObj.LockType = adLockReadOnly
6: ConnObj.Mode = adModeRead
7: If Request.Form = "" then %>
8: <HTML>
9: Input your first name.
10: <FORM Method=POST>
11: <INPUT name="fname">
12: <BR><INPUT type=submit>
13: </FORM>
14: </HTML>
15: <%else
16: name=Request.Form("fname")
17: ConnObj.Open "Driver={Microsoft Access Driver (*.mdb)};DBQ
18: Â=C:\Inetpub\databases\guestbook.mdb"
19: Line1 ="SELECT DISTINCTROW tblguestbook.* FROM tblguestbook"
20: Line2=" WHERE (((tblguestbook.fname)='" & name & "`))"
21: CommandText = Line1 & Line2
22: set RstObj = ConnObj.Execute (CommandText, RecordsAffected,
adCmdText) %>
23: <HTML>
24: Your Vistor Number is <%=RstObj("no")%>
25: </HTML>
26: <%end if%>
Dieses Programm gibt eine fehlerhafte Nummer aus, sobald sich mehr als eine Person mit dem gleichen Vornamen in der Datenbank befinden. Mit Hilfe eines der Beispiele in diesem Kapitel wird dieses Problem behoben. In Zeile zwei definieren Sie das Recordset-Objekt. Definieren Sie dieses Objekt nicht, so wird ADO automatisch ein Objekt erstellen. Der Nachteil ist jedoch, daß Sie dann keine Kontrolle über die Eigenschaften des Objektes haben.
In den Zeilen vier und fünf definieren Sie die Eigenschaften für diesen Record-Set. Sie müssen die meisten Eigenschaften setzen, bevor Sie das Record-Set öffnen. Setzen Sie nur jene Eigenschaften, die für Ihre Arbeit nötig sind. Weiterführende Informationen über CursorTypes und LockTypes erhalten Sie in späteren Kapiteln.
Abbildung 8.4: |
Abbildung 8.5: |
Sollten Sie mit der Performance nicht zufrieden sein, so können Sie ADO so einstellen, daß es alle Objekte, inklusive der Default-Eigenschaften, für Sie erstellt. Die Default-Eigenschaften für ein Record-Set sind adForwardOnly und adLockReadOnly. |
Der Code in den Zeilen 7 bis 15 verarbeitet das Formular. Sie sollten über genügend Kenntnisse in Sachen VBScript verfügen, um den Code verfolgen zu können. Ist die Request.Form-Collection nicht verfügbar, wird die Form angezeigt. Sollte dies nicht der Fall sein, wird auf die Datenbank zugegriffen und das Resultat ausgegeben.
Als nächstes interessiert uns die Zeile 22 des Listings. An dieser Stelle wird die Methode Execute nochmals verwendet. Es bestehen jedoch zwei Unterschiede zwischen dieser Zeile und Zeile 11. Da Ihre Befehle an dieser Stelle Resultate erhalten, müssen Sie die Argumente in Klammern setzen. Des weiteren müssen Sie einen Platz bereitstellen, in welchem die Resultate abgelgt werden. Hervorragend dafür geeignet ist das Recordset-Objekt. Beachten Sie bitte an dieser Stelle, daß Sie das Keyword Set benutzen.
Zu guter Letzt geben Sie den Wert eines Ihrer Felder aus. Um auf den Wert eines Feldes zuzugreifen, müssen Sie lediglich dasselbe Formular wie in Zeile 24 benutzen. Stellen Sie sicher, daß Sie den Feldnamen in Anführungszeichen gesetzt haben.
So, bis jetzt haben Sie Verbindungen und Record-Sets erstellt, es fehlen Ihnen jedoch die notwendigen Tools, um damit etwas anfangen zu können. Im nächsten Kapitel erfahren Sie, wie Sie sich innerhalb von Record-Sets bewegen und in diesen Veränderungen vornehmen können.
Die Navigation innerhalb eines Record-Sets
Ein Record-Set ist in der Lage, mehrere Einträge zu enthalten. Es ist stets von größter Wichtigkeit zu wissen, wo Sie sich innerhalb eines Record-Sets befinden, da alle Veränderungen und Lesevorgänge Eintrag für Eintrag durchgenommen werden. Veränderungen und Lesevorgänge beziehen sich deshalb immer nur auf den aktuellen Eintrag. Es gibt drei Wege, den aktuellen Eintrag in einem Record-Set zu verändern. Diese sind »incrementally forward«, »incrementally backward« und über Bookmarks.
Das Listing 8.4 mit der Bezeichnung few.asp ist eine Applikation, die alle Einträge eines Gästebuchs innerhalb einer HTML-Tabelle ausgibt.
Listing 8.4: Diese Applikation listet alle Einträge eines Gästebuchs auf
1: <!--#include virtual="/ASPSAMP/SAMPLES/ADOVBS.INC"-->
2: <%Set ConnObj = Server.CreateObject("ADODB.Connection")
3: Set RstObj = Server.CreateObject("ADODB.Recordset")
4: ConnObj.Open "guestbook"
5: RstObj.Open "tblguestbook",ConnObj,adOpenKeySet,,adCmdTable
6: RstObj.MoveLast
7: vistors = RstObj("no")
8: RstObj.MoveFirst %>
9: <HTML> <HEAD> <TITLE>Guest Book</TITLE> </HEAD> <BODY>
10: <%=vistors%> people have signed the guestbook.<P>
11: <TABLE BORDER=0><TR>
12: <TH>NO.</TH><TH colspan=2>Name</TH><TH>Phone</TH><TH>Email</TH>
13: <TH>HomePage</TH><TH>Date Added</TH></TR>
14: <%do until RstObj.EOF%>
15: <TR>
16: <%for each x in RstObj.Fields
17: if x.Value <> "" then%>
18: <TD><%=Server.HTMLEncode(x.Value)%></TD>
19: <%else%>
20: <TD>NULL</TD>
21: <%end if
22: next
23: RstObj.MoveNext%>
24: </TR>
25: <%Loop%>
26: </TABLE> </BODY> </HTML>
Die Ausgabe des Listings 8.4 sehen Sie in Abbildung 8.6.
Abbildung 8.6: |
In view.asp benutzen Sie ein DSN, um eine Verbindung zu öffnen. Das Objekt Recordset wurde über die Methode Open geöffnet. Die Syntax für Methode und Objekt lautet wie folgt:
RstObj.Open Source, ActiveConnection, CursorType, LockType, Options
In diesem Fall war die Quelle eine Tabelle in der ConnObj-Verbindung, die durch adCmdTable als Options-Argument näher spezifiziert wurde. Weiterhin wurde der Cursor von adForwardOnly in adKeySet geändert, so daß Sie sich in Ihrem Record-Set frei bewegen können.
Um Ihre Daten anzuzeigen, benutzten Sie die Eigenschaft Value der Fields-Collection. Die Fields-Collection beinhaltet alle Fields-Objekte Ihrer Datenbank. Dadurch sind Sie in der Lage, sich durch jedes Feld innerhalb der Fields-Collection (Zeile 16) zu bewegen und somit den Wert, den die Value-Eigenschaft benutzt, zu erhalten (Zeile 18), ohne jedes Feld einzeln aufzurufen. Der Code benutzt die HTMLEncode-Methode in Zeile 12, um den Wert den entsprechenden Feldern im Client-Browser auszugeben.
Wenn Sie mit Datenbanken arbeiten, ist es von großer Bedeutung zu wissen, wie die NULL-Werte (Zeile 17) gehandhabt werden. Null-Werte eines Feldes können zu einer ganzen Reihe von Problemen führen. Deshalb sollte Ihre Datenbank in der Lage sein, mit diesen Werten umzugehen. Wenn Sie Daten extrahieren, so sollten Sie immer im Hinterkopf behalten, daß ASP-Methoden, wie beispielsweise HTMLEncode, nicht in der Lage sind, Null-Strings zu verarbeiten, so daß Ihre Applikation einen Fehler generieren wird.
Öffnen Sie einen Record-Set, so ist der gegenwärtige Eintrag Ihr erster Eintrag. Um sich innerhalb der Einträge zu bewegen, können Sie die traditionelle Single-Step-Methode oder die Sized-Step-Methode, die wir später noch besprechen, benutzen. In diesem Kapitel besprechen wir erst einmal die Single-Step-Methode.
MoveNext und MovePrevious sind beides Single-Step-Methoden und erledigen exakt das, was Sie sich wahrscheinlich schon vorstellen - das schrittweisen Bewegen von Datensatz zu Datensatz. MoveFirst und MoveLast springen zum ersten bzw. letzten Eintrag Ihrer Datenbank.
Neben allen Einträgen in einem Record-Set gibt es zwei weitere Positionen, die von Bedeutung sind - die BOF-Position vor dem ersten Eintrag und die EOF-Position nach dem letzten Eintrag. Wollen Sie sich eine Stelle nach der EOF- bzw. vor die BOF-Position bewegen, so werden Sie mit Sicherheit eine Fehlermeldung erhalten. Befinden Sie sich in der BOF- oder EOF-Position, wird die entsprechende BOF- oder EOF-Eigenschaft auf TRUE gesetzt. Um derartige Fehler zu vermeiden, überprüfen Sie doch bitte die BOF- und EOF-Eigenschaften unter Zuhilfenahme eines if...then-Statements, oder benutzen Sie eine while/until-Schleife.
In Listing 8.4 starten Sie mit dem letzten Eintrag im Record-Set, um die Gesamtzahl an Besuchern zu erhalten (Zeilen 6 und 7). Im Anschluß daran bewegen Sie sich zum Anfang des Record-Sets zurück (Zeile 8), so daß Sie sich Schritt für Schritt durch die Datensätze bewegen können. Sie bewegen sich durch die Datensätze, indem Sie die Methode MoveNext benutzen (Zeile 23), die eine until-Schleife eingebettet ist, um zu vermeiden, daß Sie sich zur EOF-Position begeben.
Was Sie tun sollen |
Was nicht | |
Versuchen Sie nicht, den aktuellen Datenbank-Eintrag zu lesen bzw. zu modifizieren, wenn die BOF- oder EOF-Eigenschaft auf TRUE gesetzt ist. Wenn eine der Eigenschaften auf TRUE steht, bedeutet dies, daß es derzeit keinen aktuellen Eintrag gibt. Sollten Sie dennoch versuchen, einen derartigen Eintrag zu lesen oder zu modifizieren, erhalten Sie eine Fehlermeldung. |
ADO besitzt zwei weitere Features zur Navigation, die jedoch ein wenig schwieriger zu handhaben sind. Das erste nennt sich Pages, welches willkürlich zusammengestellte Gruppen von Einträgen enthält, die als aktuelle Einträge agieren. Pages sind nicht sehr hilfreich zum Editieren, da Sie die gesamte Seite »locken« müssen, um einen bestimmten Eintrag zu ändern. Pages werden hauptsächlich für Report-Funktionen genutzt. ActiveX-Steuerungen, wie etwa ActiveX, können Sie dazu nutzen, um sich von Seite zu Seite bewegen. |
Das zweite Feature nennt sich Bookmark. Bookmarks erlauben Ihnen das sprungweise Bewegen innerhalb eines Record-Sets. Ihr Data-Provider muß beide Features unterstützen, bevor Sie diese nutzen können. Mehr Informationen finden Sie in Microsofts ADO-Dokumentation.
Wenn Sie sich vorwärts oder rückwärts innerhalb eines Record-Sets bewegen, können Sie die Schrittweite unter Zuhilfenahme der Move-Methode wie folgt spezifizieren: RstObj.Move Numrecords , Start |
Ist NumRecords größer als 0, so bewegen Sie sich vorwärts. Ist der Wert kleiner als 0, so bewegen Sie sich rückwärts. Start ist ein optionales Argument, das einen Bookmark spezifiziert. Achten Sie bitte darauf, daß Sie sich nicht vor bzw. hinter BOF oder EOF bewegen.
Benutzen Sie die Filter-Eigenschaft zur Suche nach Informationen
Die Filter-Eigenschaft erlaubt es Ihnen, ein Record-Set zu filtern, um einen Eintrag zu finden, der Ihren Kriterien entspricht. Es gibt drei Wege, einen Record-Set zu filtern - mit Hilfe von Kriterium-Strings, Bookmark-Arrays oder Kriterium-Konstanten.
Listing 8.5 mit der Bezeichnung filter.asp, beinhaltet den Code einer Applikation, die es Ihnen gestattet einen bestimmten Eintrag, basierend auf dem Vornamen, zu finden. Nahezu der gesamte Code, mit Ausnahme der Filterroutine, basiert auf Code, den wir schon einmal besprochen haben. Die Resultate des Codes ersehen Sie aus Abbildung 8.7.
Listing 8.5: Die Filterroutine filter.asp
1: <!--#include virtual="/ASPSAMP/SAMPLES/ADOVBS.INC"-->
2: <%Set ConnObj = Server.CreateObject("ADODB.Connection")
3: Set RstObj = Server.CreateObject("ADODB.Recordset")
4: ConnObj.Open "guestbook"
5: if Request.Form = "" then %>
6: <HTML>
7: Filter on First Name.
8: <FORM method=POST> <TABLE>
9: <TR><TD>First Name:</TD><TD><input name ="fname"></TD></TR>
10: </TABLE> <P> <INPUT type=submit> <INPUT type=reset>
11: </FORM></HTML>
12: <%else
13: RstObj.Open "tblguestbook",ConnObj,adOpenKeySet,adCmdTable
14: RstObj.Filter = "[fname] = ô" & Request.Form("fname") & "ô"%>
15: <HTML> <HEAD> <TITLE>Guest Book</TITLE> </HEAD> <BODY>
16: Filter = "[fname] = ô<%=Request.Form("fname")%>õ"
17: <P><TABLE BORDER=0><TR>
18: <TH>No.<TH colspan=2>Name</TH><TH>Phone</TH><TH>Email</TH>
19: <TH>HomePage</TH><TH>Date Added</TH></TR>
20: <%do until RstObj.EOF%>
21: <TR>
22: <%for each field in RstObj.Fields
23: if field.Value <> "" then%>
24: <TD><%=Server.HTMLEncode(field.Value)%></TD>
25: <%else%>
26: <TD>NULL</TD>
27: <%end if
28: next
29: RstObj.MoveNext%>
30: </TR>
31: <%Loop%>
32: </TABLE> </BODY> </HTML>
33: <%Rst.Filter adFilterNone
34: end if%>
Kriterium-Strings gestatten es, den Record-Set auf Basis logischer Feld/Namen-Paare zu durchsuchen. Die Feldnamen sollten in Klammern erscheinen. Wie die Werte erscheinen, hängt vom Daten-Typ des entsprechenden Feldes ab. Strings sollten in einfachen Anführungszeichen (´) und Daten in Doppelkreuzzeichen (#) erscheinen. Listing 8.5 benutzt eine einfache Anweisung, um den entsprechenden Datensatz herauszufiltern (Zeile 14).
Ein Kriterium-String kann auf einer Vielzahl von Klauseln basieren, die durch AND-Statements verknüpft sind. Insgesamt gibt es sieben Operatoren: =, <, >, <=, >=, <> und Like. Sollte der Operator Like sein, darf der Wert über Wildcards * oder % als letztes Zeichen im String verfügen. Sie können ebenfalls kompliziertere Filter wie den folgenden aufbauen, der einen Namen und eine Telefonnummer berücksichtigt:
RstObj.Filter = "[name] = 'Kelly' AND [phone] LIKE '706*'"
Abbildung 8.7: |
Die Benutzung von Klammern in Verbindung mit Feldnamen ist nur dann notwendig, wenn der Feldname Leerzeichen enthält. Des weiteren können Sie Feldnamen durch Klammern trennen. Dies empfiehlt sich, da dadurch eine bessere Lesbarkeit erreicht wird. |
Listing 8.5 benutzt noch einen weiteren Filtertyp - die Kriterium-Konstante (Zeile 33). Kriterium-Konstanten filtern einen Eintrag unter Zuhilfenahme von innewohnenden Attributen heraus. Diese Attribute finden Sie in Tabelle 8.4. Kriterium-Konstanten werden von ADO ebenfalls als FilterGroupEnum-Werte bezeichnet.
Tabelle 8.4: Gültige FilterGroupEnum-Werte
Konstante |
Filteraktion |
adFilterNone |
Entfernt alle Filter und stellt den Zustand aller Einträge wieder her. Das Setzen des Filters auf einen Null-String (RstObj.Filter = "") hat den gleichen Effekt. |
adFilterPendingRecords |
Der Filter zeigt alle Einträge, die im Batch-Modus bearbeitet, jedoch nicht versandt wurden. |
adFilterAffectedRecords |
Der Filter zeigt alle Einträge, die als letztes durch die Methoden CancelBatch, Delete, Resync oder UpdateBatch bearbeitet wurden. |
adFilterFetchedRecords |
Der Filter zeigt die Resultate des letzten Zugriffs auf die Datenbank an. |
Ihr Filter in Zeile 33 dient keinem Zweck mit der Ausname der Illustration von Kriterium-Konstanten, da der Record-Set am Ende der Seite sowieso geschlossen wird.
Das Hinzufügen, Löschen und Modifizieren von Einträgen
Wenn Sie Datenbankeinträge modifizieren oder hinzufügen möchten, stehen Ihnen verschiedene Möglichkeiten zur Verfügung. Das »Blind Adding« von Einträgen benötigt keinen Cursor oder Record-Set. Sie können diese Arbeit mit dem SQL-Statement INSERT INTO und der Execute-Methode der Objekte Connection oder Command durchführen (Listing 8.1). Das selbe gilt für »Blind Delete«.
Was Sie tun sollen |
Was nicht | |
Benutzen Sie SQL-Statements oder gespeicherte Prozeduren, um Daten eines Daten-Providers ohne Zuhilfenahme eines Record-Sets hinzuzufügen oder zu löschen. Dies spart Ihnen eine Menge Zeit und ist wesentlich effizienter als die AddNew- oder Delete-Methode, die wir später noch besprechen werden. Benutzen Sie nach Möglichkeit immer SQL-Statements oder bereits gespeicherte Prozeduren. |
Müssen Sie die Daten lesen, bevor Sie zu einem Record-Set hinzugefügt werden, so können Sie die Methode AddNew benutzen. Um einen Eintrag zu löschen, müssen Sie die Methode Delete anwenden.
In diesem Kapitel erstellen Sie eine Applikation, die es Ihnen gestattet, ein Gästebuch einzusehen. Des weiteren haben Sie die Wahl, einen neuen Eintrag zu erstellen, einen existierenden zu editieren oder einen Eintrag zu löschen. Diese Applikation ist in zwei Dateien unterteilt. Die Datei listedit.asp finden Sie auf der MCP-Homepage. Bei dieser Datei handelt es sich um eine leichte Modifikation von view.asp aus Listing 8.4. Abbildung 8.8 zeigt die Ausgabe des Listings listedit.asp.
Abbildung 8.8: |
Um einen Eintrag zu ändern oder zu löschen, klicken Sie auf den entsprechenden Eintrag mit der Besuchernummer. Einen neuen Eintrag fügen Sie hinzu, indem Sie auf die Schaltfläche am Anfang der Seite klicken. Listedit.asp übergibt die Ausgabe an die Datei edit.asp aus Listing 8.6.
Sollten Sie sich dafür entscheiden, einen neuen Eintrag hinzuzufügen, so schaut die Ausgabe von edit.asp wie in Abbildung 8.9 aus. Haben Sie vor, einen existierenden Eintrag zu modifizieren, so steht Ihnen dazu die Maske aus Abbildung 8.10 zur Verfügung.
Abbildung 8.9: |
Abbildung 8.10: |
Listing 8.6: Der ASP-Code für edit.asp
1: <!--#include virtual="/ASPSAMP/SAMPLES/ADOVBS.INC"-->
2: <%if Request.Form("action")="" then
3: ' part one display the forms
4: myarray = ARRAY ("First Name:","Last Name:","Phone:","Email:","Home
Page:")
5: set RstObj = Session("RstObj")
6: if Request.Form("button") <> "add" then
7: RstObj.Filter = "[no] = `" & Request.Form("button") & "`"
8: Session("no") = Request.Form("button")
9: end if%>
10: <HTML> <HEAD> <TITLE>Guestbook Form</TITLE> </HEAD> <BODY>
11: <P align=center> Please fill out the form below to add your
12:Âinformation to the guestbook.
13: <FORM method = POST> <TABLE>
14: <%for each x in RstObj.Fields
15: if x.Name <> "no" then
16: if x.Name <> "dateadded" then %>
17: <TR><TD><%=myarray(count)%></TD>
18: <%count = count + 1
19: if Request.Form("button") <> "add" then%>
20: <TD><input name ="<%=x.Name%>" value="<%=x.Value%>"></TD></TR>
21: <%else%>
22: <TD><input name ="<%=x.Name%>"></TD></TR>
23: <%end if
24: end if
25: end if
26: next%>
27: </TABLE>
28: <%if Request.Form("button") <> "add" then%>
29: <INPUT type=submit name="action" value="Submit Changes">
30: <INPUT type=submit name="action" value="Delete Record">
31: <INPUT type=submit name="action" value="Abandon Changes">
32: <%else%>
33: <INPUT type=submit name="action" value="Add">
34: <%end if%>
35: </FORM> </BODY> </HTML>
36: <%'part 2 handle actions
37: else
38: Set ConnObj = Server.CreateObject("ADODB.Connection")
39: Set RstObj = Server.CreateObject("ADODB.Recordset")
40: ConnObj.Open "guestbook"
41: RstObj.Open "tblguestbook",ConnObj,adOpenKeySet,adCmdTable
42: Select Case Request.Form("action")
43: Case "Add"
44: count =1
45: RstObj.AddNew
46: for each x in Request.Form
47: if Request.Form(x) <> "" then
48: if x <> "ACTION" then%>
49: <% RstObj(x) = Request.Form(x)
50: end if
51: end if
52: next
53: RstObj("dateadded")=now()
54: RstObj.Update %>
55: <HTML>
56: Record Added<BR>
57: Click <a href="listedit.asp">here</a> to see new entry
58: </HTML>
59: <%Case "Delete Record"
60: RstObj.Filter = "[no] = `" & Session("no") & "`"
61: RstObj.Delete%>
62: <HTML>
63: Record Deleted<BR>
64: Click <a href="listedit.asp">here</a> to go back to table.
65: </HTML>
66: <%Case "Submit Changes"
67: RstObj.Filter = "[no] = `" & Session("no") & "`"
68: for each x in Request.Form
69: if Request.Form(x) <> "" then
70: if x <> "ACTION" then
71: RstObj(x)=Request.Form(x)
72: end if
73: end if
74: next%>
75: <HTML>
76: Record Changed<BR>
77: Click <a href="listedit.asp">here</a> to see changes.
78: </HTML>
79: <%Case "Abandon Changes"
80: Response.Redirect("listedit.asp")
81: end select
82: end if%>
Das Listing edit.asp besteht aus insgesamt zwei Teilen. Am Programmstart überprüft das Programm, ob irgendwelche Aktionen angefordert wurden (Zeile 2). Ist dies nicht der Fall, erscheint entweder der Bildschirm zum Hinzufügen eines Datensatzes (siehe Abbildung 8.9) oder der Edit-Bildschirm (siehe Abbildung 8.10), je nachdem, welchen Wert die Variable button (Zeile 6) an listedit.asp übergeben hat. Die entsprechende Form wird angezeigt, und Sie haben die Möglichkeit, eine der Schaltflächen zu betätigen. Jede dieser Schaltflächen führt eine spezielle Aktion aus, die auf der Variablen action beruhen.
Sollten Sie einen Eintrag modifizieren (button<>"add"), so wird die Besuchernummer von listedit.asp übergeben, um eine entsprechende Filterung vorzunehmen (Zeile 7). Die Informationen des aktuellen Eintrags werden dann benutzt, um die Werte des Form-Felds (Zeile 20) zu modifizieren.
Was Sie tun sollen |
Was nicht | |
Benutzen Sie das Session-Objekt, um Daten darin zu speichern, nur für Reportzwecke. Listedit.asp speichert eine Kopie des Record-Sets im Sessions-Objekt (Kapitel 4), so das es in Zeile 5 des Listings edit.asp genutzt werden kann. Diese Technik können Sie nur für Report-Zwecke verwenden, da Sie nicht in der Lage sind, Daten innerhalb dieses Objektes zu modifizieren. |
Der zweite Teil des Listings ist der eigentlich interessante. Dieser Teil behandelt die Aktionen des Hinzufügens, Löschens und Modifizierens von Objekten. Der Code benutzt die Methode select case, die sehr hilfreich ist, wenn Ihre Variable mehr als zwei Zustände zuläßt.
Um einen Eintrag hinzuzufügen, benutzen Sie bitte die AddNew-Methode. Es gibt zwei Wege, um diese Methode aufzurufen. Sie können die Felder und deren Werte im folgenden Format übergeben, wobei Fields und Values Arrys sind:
RstObj.AddNew fields, Values
Änderungen, die vorgenommen werden, werden sofort zum Record-Set versendet.
Alternativ können Sie Felder in der Art und Weise hinzufügen, wie dies aus den Zeilen 45 bis 54 mit Hilfe der Methode Update zu ersehen ist. Änderungen in der Datenbank werden nicht versendet, bis nicht die Methode Update aufgerufen wurde. Sollten Sie Ihre Änderungen verwerfen wollen, so müssen Sie die Methode CancelUpdate aufrufen.
Um einen Eintrag zu editieren, benötigen Sie als erstes einen entsprechenden Eintrag aus dem Record-Set. Die Zeile 67 benutzt den Wert des no-Feldes, der im Sessions-Objekt gespeichert ist. Nachdem Sie beim korrekten Eintrag angelangt sind, können Sie damit beginnen, den Eintrag zu modifizieren. In ASP gibt es keinen Edit-Modus - sie müssen es selbst erledigen. Änderungen werden sofort übermittelt, so daß Sie in Sachen Editieren sehr vorsichtig vorgehen müssen. Sollte Sie dieser Sachverhalt nicht zufriedenstellen, so benutzen Sie am besten einen Cursor, der Batch-Editing ermöglicht.
Das Löschen eines Eintrags in ADO ist denkbar einfach. Stellen Sie sicher, daß Sie sich im richtigen Eintrag befinden (Zeile 60), und rufen Sie dann die Methode Delete (Zeile 61) auf. Der aktuelle Datensatz wird zwar gelöscht, Ihre Position im Record-Set verändert sich jedoch nicht. Nachdem Sie sich von einem gelöschten Eintrag weg bewegt haben, ist dieser endgültig verloren. Klicken Sie auf die Schaltfläche Abandon Changes in Abbildung 8.10, so werden Sie mit dem Listing listedit.asp verbunden.
Es gibt jetzt nur noch eine Tatsache, die Sie wissen müssen, bevor Sie mit dem nächsten Kapitel starten. Der Code wurde für eine einfache Verarbeitung geplant. Die Namen der Variablen beziehen sich exakt auf die gleichen Namen der entsprechenden Felder innerhalb eines HTML-Formulars einer Datenbank. Diese Tatsache macht es dank der Verwendung von Schleifen sehr einfach, Informationen schnell zu verarbeiten.
Das Command-Objekt bietet Ihnen einen anderen Weg zur Konstruktion und Erstellung von Abbildungen eines Recordset-Objektes. Das Command-Objekt repräsentiert einen Befehl, der vom Data-Provider verarbeitet wird. Da nicht alle Daten-Provider die Möglichkeit haben, Kommandos zu verarbeiten, handelt es sich bei diesem Objekt um eine optionale Komponente. Die meisten Daten-Provider jedoch unterstützen die Verarbeitung von Kommandos sowie Parametern. Die Hauptanwendungsgebiete dieses Objekts ist die Speicherung von Prozeduren sowie die Benutzung von Parametern.
Das Command-Objekt und die Parameters-Collection
Parameter sind Platzhalter in ihren Kommandos bzw. Prozeduren. Parameterabhängige Querys und Prozeduren sind in der Lage, Parameter während der Laufzeit eines Programmes zu akzeptieren. Ein Parameter ähnelt einer Variablen zumindest in der Tatsache, was die Speicherung eines Wertes betrifft. Es gibt jedoch einen großen Unterschied in ADO: Alle Variablen innerhalb ADOs sind vom Typ »Variant«. Parameter interagieren direkt mit dem Daten-Provider, so daß Sie die gleiche Charakteristiken wie die Felder aufweisen müssen, zu denen Sie in Beziehung stehen - eine korrekte Deklaration ist deshalb unumgänglich.
Paramterbasierende Abfragen und gespeicherte Prozeduren sind sehr hilfreich für Operationen, die Sie sehr oft ausführen. Die Benutzung von Parametern stellen eine Alternative zum Erstellen von SQL-Statements »auf die Schnelle« dar, wie Sie in findme.asp sahen (Listing 8.2).
Die Applikation aus Listing 8.7 trägt die Bezeichnung paramfindme.asp. Dabei handelt es sich um eine überarbeitete Version des Listings 8.2, das nunmehr in der Lage ist, ein paar mehr Informationen anzuzeigen. Das Listing benutzt Parameter anstelle von SQL-Statements. Zuerst geben Sie den Vornamen der Person ein, die Sie finden möchten (siehe Abbildung 8.11). Die Applikation gibt alle Einträge wieder, die diesen Vornamen aufweisen (siehe Abbildung 8.12).
Listing 8.7: Der Code für paramfindme.asp
1: <!--#include virtual="/ASPSAMP/SAMPLES/ADOVBS.INC"-->
2: <%Set ConnObj = Server.CreateObject("ADODB.Connection")
3: Set RstObj = Server.CreateObject("ADODB.Recordset")
4: set CmdObj = Server.CreateObject("ADODB.Command")
5: if Request.Form = "" then %>
6: <HTML>
7: Input your first name.
8: <FORM Method=POST>
9: <INPUT name="fname">
10: <BR><INPUT type=submit>
11: </FORM> </HTML>
12: <%else
13: ConnObj.Open "guestbook"
14: RstObj.ActiveConnection = ConnObj
15: CmdObj.ActiveConnection = ConnObj
16: CmdObj.CommandText = "Findme"
17: set ParamObj = CmdObj.CreateParameter
18: Â(,adVarChar,,50,Request.Form("fname"))
19: CmdObj.Parameters.Append ParamObj
20: set RstObj = CmdObj.Execute (,,adCmdStoredProc)%>
21: <HTML> <TABLE BORDER=0> <TR>
22: <TH>No.<TH colspan=2>Name</TH><TH>Phone</TH><TH>Email</TH>
23: <TH>HomePage</TH><TH>Date Added</TH></TR>
24: <%do until RstObj.EOF%>
25: <TR>
26: <%for each x in RstObj.Fields
27: if x.Value <> "" then%>
28: <TD><%=Server.HTMLEncode(x.Value)%></TD>
29: <%else%>
30: <TD>NULL</TD>
31: <%end if
32: next
33: RstObj.MoveNext%>
34: </TR>
35: <%Loop%>
36: </TABLE> </HTML>
37: <%end if%>
Wieder einmal haben wir den Code aus anderen Listings recycled. Der Code arbeitet mit einer gespeicherten Abfrage der Datenbank mit der Bezeichnung findme. Die Prozedur hat genau einen Parameter - den Vornamen. Da der Daten-Provider nicht in der Lage ist, mit dem Anwender zur Laufzeit der Applikation zu kommunizieren, um den Wert des Parameters zu erhalten, müssen Sie diesen Parameter erstellen und zum Daten-Provider versenden. Es ist sogar möglich, textbasiernende SQL-Kommandos zu verwenden, die Parameter enthalten. Sie können die Text-Kommandos und Parameter als Teil des Command-Objekts aufnehmen und diese zum Daten-Provider zur weiteren Verarbeitung senden.
Abbildung 8.11: |
Abbildung 8.12: |
Die Parameters-Collection greift auf das Command-Objekt zurück, so daß Sie vor der Erstellung von Parametern erst einmal ein Command-Objekt (Zeile 4) erstellen müssen. Nachdem Sie dieses Objekt erstellt haben, müssen Sie es in Beziehung mit dem Connection-Objekt mittels der ActiveConnection-Eigenschaft (Zeile 15) bringen. Diese Eigenschaft müssen Sie vor dem Aufruf der Execute-Methode setzen, da ansonsten eine Fehlermeldung ausgegeben wird.
Wenn Sie einen Parameter erstellen, so sollten Sie über vier Dinge Bescheid wissen. Sie müssen den Namen des Parameters, den Wert, welchen Sie dem Parameter zuweisen möchten, den Daten-Typ des Feldes sowie die Größe des Feldes, das sich auf den Parameter bezieht, kennen. Benutzen Sie die Methode CreateParameter, um einen Parameter wie folgt zu erstellen:
Set ParamObj = CmdObj.CreateParameter(Name,Type,Size,Value)
Der Name eines Parameters ist von nur geringer Bedeutung, solange Sie die Reihenfolge wissen, nach der die Parameter benötigt werden. Sie sollten sicherstellen, daß die Eigenschaften der Parameter zu den entsprechenden Feldern passen. Das Argument size ist nicht unbedingt notwendig. Das hängt jedoch in erster Linie davon ab, auf welchem Daten-Typ das jeweilige Feld beruht. |
Wenn Sie genau über Ihre Datenbank Bescheid wissen und diese mit den korrekten Werten für die Argumente type und size versorgen, sollten Sie keinerlei Probleme haben. Der Typ AdVarChar, welcher in ASP/ADO eine dominante Stellung einnimmt, benötigt das Argument size. Einige andere Daten-Typen benötigen keinerlei size-Argumente. Weiterführende Informationen über Daten-Typen und deren ADO-Konstanten erhalten Sie aus Microsofts ADO-Dokumentation.
Nachdem die Parameter erstellt wurden, müssen Sie diese zur Parameters-Collection hinzufügen. Dies geschieht mittels der Append-Methode, wie aus Zeile 19 ersichtlich ist. Sie können Parameter aus der Collection löschen, indem Sie die Delete-Methode mit folgender Syntax einsetzen:
CmdObj.Parameters.Delete ParamObj
Nun ist nahezu alles notwendige getan. Sie müssen jetzt lediglich nur noch die Eigenschaft CommandText des Command-Objektes setzen. Die Zeile 16 setzt diese zu dem Namen der gespeicherten Prozedur (findme). Nachdem dies durchgeführt wurde, müssen Sie nur noch die Methode Execute aufrufen, um sämtliche Dinge an das Ende des Daten-Providers zu schicken.
Gibt Ihr Kommando einen Eintrag zurück, so müssen Sie das Resultat in einem Record-Set speichern, indem Sie das Schlüsselwort Set (Zeile 20) benutzen. Klammern sind notwendig, sollte Ihr Kommando einen Record-Set zurückgeben. Andernfalls besteht keine Notwendigkeit, Klammern einzusetzen. Sie müssen dem Daten-Provider mitteilen, welcher Kommando-Typ (adStoreProc) empfangen wurde - das hilft Zeit zu sparen.
Entwickeln Sie ein Verständnis für Record-Sets
Dieses Kapitel ist ein bißchen kompliziert, jedoch unbedingt notwendig für eine erfolgreiche Arbeit in Sachen ADO. Nachdem Sie dieses Kapitel durchgearbeitet haben, werden Sie ein besseres Verständnis für Record-Sets und Cursors haben.
Bevor Sie in die Welt der Record-Sets eintauchen, werfen Sie doch mal einen Blick auf die Funktionsweise des Informationsaustausches mit dem Daten-Provider im Bereich der Erstellung von Einträgen. Es ist natürlich auch möglich, ADO zu benutzen, ohne daß Sie etwas über OLE oder ODBC wissen. Sie können jedoch wesentlich effizienter arbeiten mit einem Verständnis für die ADO-Materie. OLE DB (Object Linking and Embedding applied to database) ist Microsofts neues API (Object-Oriented Application Interface).
APIs besitzen eine Low-Level-Kodierung, die Ihnen als Web-Entwickler sehr hilfreich sein kann. ActiveX an sich ist eine neutrale Sprache mit OLE-Funktionalität. ADO ist ein ActiveX-Produkt, das dem Anwender die Vorteile von OLE DB ohne Kenntnisse in Sachen C++ bereitstellt.
OLE DB wurde kreiert, um dem Entwickler Zugriff auf eine breite Palette von Daten-Speicherungs-Systemen zu gewährleisten. Weiterhin gibt OLE DB Ihnen ein Interface zu relationalen Datenbanken, die auf Basis von SQL funktionieren. OLE DB soll OLE nicht ergänzen, sondern um eine Vielzahl von Funktionen erweitern.
Innerhalb OLE DBs gibt es drei Kategorien: Hierzu zählen »Interfaces Data Consumers«, »Data Providers« sowie »Service Providers«. Consumer erhalten die Daten über ein OLE DB-Interface, wo hingegen Provider die Daten zu einem OLE-Interface schicken. Im Sinne dieses Kapitels handelt es sich bei der ADO-Applikation um den Consumer und bei ODBC um den Provider. Service Provider sind beides - Data Consumers und Provider.
OLE DB 1.0 stellen Daten in tabellarischer Form zur Verfügung - unabhängig von ihrer ursprünglichen Form. Aus diesem Grund benutzen wir ODBC, um SQL-Daten zu speichern. ADO und OLE DB sind in der Lage, E-Mails, Spreadsheets oder Daten welcher Art auch immer, zu bearbeiten bzw. zu speichern.
Record-Sets und Cursors
Die Aufgabe einer Datenbank ist es, Daten zur Verfügung zu stellen, neue Datensätze zu erstellen bzw. zu editieren. Nahezu alle diese Aufgaben können mittels des Recordset-Objekts durchgeführt werden. Die Idee hinter ADO ist es, dem Anwender einen einfachen Zugriff auf Daten zu gewährleisten. Verstehen Sie jedoch nicht die Funktionsweise von Record-Sets inklusive dem Recordset-Objekt in ADO, so werden Sie Ihr System nur schwer in Sachen Performance und Datenschutz optimieren können.
ADO stellt Daten in tabellarischer Form bereit. Dieser Umstand bedarf besonderer Berücksichtigung, da die entsprechenden Daten nicht unbedingt in tabellarischer Form vorliegen (Text-Dateien). Jede Zeile in einer Tabelle ist als kompletter Eintrag anzusehen. Record-Sets in ADO sind Container-Objekte für Einträge, in denen Daten in tabellarischer Form abgespeichert sind. Es wichtig, daß Sie begreifen, daß Record-Sets eine Darstellung Ihrer Daten sind, die aus einer entsprechenden Daten-Quelle stammen - jedoch nicht die Daten selbst. ADO arbeitet nicht direkt mit den gespeicherten Daten zusammen. Es ist nicht in der Lage, Daten direkt vom Daten-Provider zu lesen bzw. in ihn hinein zu schreiben. Das Lesen von Daten, deren Modifikation und das Löschen der Daten muß innerhalb der Record-Sets geschehen.
Wenn Sie sich innerhalb eines Record-Sets befinden, müssen drei Dinge festgestellt werden - Ihr Standort, Ihre Navigationsmöglichkeiten und die Verbindung zum Daten-Provider. Cursors bestimmen das Verhalten Ihres Record-Sets.
Die Navigation innerhalb eines Record-Sets ist eine sehr komplexe Sache. Das schrittweise Bewegen von Eintrag zu Eintrag ist sehr einfach, doch das Feststellen Ihrer aktuellen Position innerhalb einer Datenbank ist nicht so einfach - vom Springen innerhalb einer Datenbank mal ganz abgesehen. Dies hat verschiedenste Gründe: SQL wird benutzt, um Record-Sets zu erstellen. SQL ist eine Set-basierende Sprache ohne Definitionen von physikalischen Zeilen innerhalb eines Sets. Der Cursor transformiert den Eintrag in Spalten und Zeilen. Es gibt keine Nummern für Einträge in ODBC, da es keine physikalischen Zeilen gibt. Der Platz eines Eintrages innerhalb einer Datenbank wird durch die SQL-Statements WHERE und ORDER BY festgestellt. Um einen Bezug auf einen bestimmten Eintrag festzulegen, müssen Sie Bookmarks benutzen. Nicht alle Cursors unterstützen Bookmarks (siehe Tabelle 8.6).
Lassen Sie sich durch diese Diskussion über Bookmarks nicht abschrecken. Sie sollten nur wissen, daß wenn Sie direkt zu einem Eintrag im Record-Set springen möchten, Ihr Cursor und Ihr Daten-Provider Bookmarks unterstützen müssen.
Konkurrierendes und einmischendes Verhalten
Das Internet und Intranets sind Multi-User-Umgebungen. Es ist möglich, einer Vielzahl von Anwendern zu erlauben, daß diese gleichzeitig auf bestimmte Datensätze zugreifen können. Bei Lesevorgängen stellt dies in aller Regel kein Problem dar. Schwieriger wird es jedoch, wenn zwei Personen gleichzeitig versuchen, einen Datensatz zu modifizieren. Hierbei kann es zu erheblichen Störungen kommen. Wurden Daten von einer Person editiert und werden diese anschließend von einer anderen benutzt, kann es zu Interferenz-Problemen kommen. Darunter ist das Verändern von Daten während einer Operation zu verstehen.
Weder Interferenz noch konkurrierendes Verhalten sind wünschenswerte Zustände, doch lassen diese Aspekte sich kaum vermeiden. Das Problem ist, daß Sie es einer Vielzahl von Menschen gestatten möchten, dieselben Daten zur gleichen Zeit nutzen. Eine Lösung für diesen Konflikt gibt es nicht wirklich. Je nach Ihren Bedürfnissen müssen Sie mit diesen Hindernissen leben.
Lock-Types und Isolation-Levels
Um Daten vor Verfälschung zu schützen, müssen Sie auf Locks zurückgreifen. Locks stellen sicher, daß lediglich nur ein User zu einer bestimmten Zeit einen Datensatz modifizieren kann. Es gibt drei Arten von Locks:
Tabelle 8.5 zeigt verschiedene Lock-Typen.
Tabelle 8.5: Typen von Lock
Typ |
Beschreibung |
adLockReadOnly |
Read-only. Sie können keine Daten eingeben. |
adLockPessimistic |
Pessimistic Locking sperrt die Daten, Datensatz für Datensatz bzw. Seite für Seite. Niemand ist in der Lage, den aktuellen Datensatz zu editieren. |
adLockOptimistic |
Optimistic Locking sperrt Eintrag für Eintrag. Einträge werden jedoch nur vor einem Update gesperrt werden. Zwei Anwender können zur selben Zeit ein und denselben Datensatz bearbeiten. |
adLockBatchOptimistic |
Optimistic Batch-Updates sind notwendig für ein Batch-Update. |
Wenn eine Applikation einen Cursor nutzt oder ein Anwender aus einer anderen Applikation mit einem Cursor kommuniziert, können Interferenz-Probleme auftreten. Es gibt drei Arten von Problemen mit Interacting Cursors:
Interferenzen in Transaktionen werden von der Eigenschaft IsolationLevel des Connection-Objekts gehandelt. Isolation-Levels bieten Ihnen die Möglichkeit festzustellen, wie sich Änderungen anderer Anwender auswirken.
In ADO werden Isolation-Levels in der CursorType-Eigenschaft definiert. Unterschiedliche Cursors erfordern unterschiedliche Level der Isolation. Cursor-Typen definieren des weiteren Navigations-Möglichkeiten. Die Tabelle 8.6 zeigt die unterschiedlichen Cursor-Typen auf.
Tabelle 8.6: Cursor-Typen in ADO
Name |
ADO-Konstante |
Beschreibung |
Dynamic |
adOpenDynamic |
Die ist der mächtigste und am häufigsten verwandte Cursor-Typ und benötigt eine Vielzahl von Ressourcen. Dieser Cursor-Typ ist in der Lage, Änderungen zu erkennen, die vom Anwender durchgeführt wurden. Weiterhin werden Bookmarks sowie Backward- und Forward-Navigation unterstützt. |
Keyset |
adOpenKeyset |
Der Keyset-Cursor unterstützt Bookmarks sowie Forward- und Backward-Navigation. Editierte Daten können erst eingesehen werden, wenn diese freigegeben werden. Das Hinzufügen oder Löschen von Informationen kann mit diesem Cursor nicht festgestellt werden. |
Static |
adOpenStatic |
Dieser Cursor wird auch oft »Snapshot Cursor« genannt. Bookmarks sowie Forward- und Backward-Navigation werden unterstützt. Änderungen sind jedoch nicht feststellbar. |
Forward Only |
adOpenForwardOnly |
Dieser Cursor verfügt über die gleichen Fähigkeiten wie der Static-Cursor, mit der Ausnahme, daß lediglich Forward-Navigation möglich ist. |
Wählen Sie den richtigen Cursor aus
Die Wahl des richtigen Cursors ist von großer Bedeutung für Ihre zukünftige Applikation. Sie müssen vor allem wissen, was Sie tun wollen. Eine gute Planung im Vorfeld hilft Ihnen bei der Programmierung, eine Menge Zeit zu sparen.
Sie müssen einen Cursor-Typ auswählen, der Ihren Ansprüchen bzw. den der Applikation gerecht wird. Dies spart Ressourcen für den Daten-Provider und ADO, so daß der Client-Browser schneller die entsprechenden Ergebnisse einsehen kann. Die Wahl des falschen Cursors kann Ihre Applikation in die Knie zwingen und das Surf-Erlebnis des Internet-Reisenden zum Alptraum machen.
Einige Daten-Provider, wie beispielsweise SQL 6.5, besitzen ein Feature mit der Bezeichnung server-side cursor. Dieser Cursor-Typ senkt den Netzwerkverkehr und benutzt die Ressourcen des SQL-Servers anstelle der des IIS. |
Es gibt drei verschiedene Dinge, die Sie mit Ihren Daten anstellen müssen, um festzustellen, welchen Typ von Record-Set Sie benötigen. Vielleicht benötigen Sie lediglich einen Report, Edit-Funktionen oder die Möglichkeit zum Editieren von Datenbank-Einträgen. In vielen Fällen brauche Sie von jedem etwas in Ihrer Applikation, so das Sie innerhalb Ihres Scripts verschiedene Cursor-Typen anwenden müssen.
Die erste und einfachste Aufgabe ist die des einfachen Lese- oder Report-Vorgangs. Der Report benötigt lediglich nur die Forward-Bewegung und ein Read-only-Lock, um die meisten Aufgaben zufriedenstellend zu erfüllen - Reports erfordern keine Art der Datenmanipulation.
Im nächsten Schritt ist vielleicht das Editieren von Daten notwendig. Sie sollten zunächst entscheiden, welchen Lock-Type Sie benutzen möchten. Web-Sites mit einem hohen Verkehrsaufkommen sind eher der Wahrscheinlichkeit von konkurrierenden Editierungen ausgesetzt und benötigen ein weitergehendes Locking, um eine Daten-Verfälschung zu vermeiden. Pessimistic-Locking dürfte an dieser Stelle eine gute Wahl darstellen. Sites mit geringem Verkehrsaufkommen können diese Lock-Methode ebenfalls benutzen.
Die zweite Frage, die Sie sich stellen sollten, wäre die nach dem Typ von Isolation, den Ihre Transaktion benötigt und welche Navigations-Möglichkeiten zur Verfügung stehen sollen. Soll eine hohe Interaktivität zur Verfügung stehen (Electronic Shopping), so sollten Sie geringe Isolation-Levels und eine hohe Lock-Stufe wählen. Bei Applikationen, die eine Anwenderbeeinflußung weitgehend ausschließen, müssen Sie die gegenteilige Konstellation wählen.
Zu guter Letzt gibt es manche Situationen, die Einträge erfordern, welche »blindly added« hinzugefügt werden müssen (etwa in einem Gästebuch). Obwohl Sie die Methoden AddNew oder Delete (um Einträge zu löschen) anwenden können, führen diese nur zu einem schlechten Ergebnis. Sie haben die Möglichkeit, Einträge direkt hinzuzufügen oder zu löschen, ohne daß Sie einen speziellen Cursor definieren müssen. Benutzen Sie einfache SQL-Kommandos - der Data-Provider übernimmt alles andere.
Zusammenfassung
In diesem Kapitel lernten Sie viele hilfreiche Dinge über Data-Access-Komponenten und ActiveX-Data-Objekte. Die Vorteile von ADO liegen in den Bereichen Geschwindigkeit, geringer Speicherplatz-Bedarf, geringe Arbeitsspeicher-Auslastung und die Möglichkeit der Funktion in einer verbindungslosen Umgebung wie die des Internet. ADO bekommt seine Daten von einem Data-Provider in tabellarischer Form. Das wichtigste Objekt innerhalb ADOs ist das Recordset-Objekt. Die anderen Objekte und Methoden gestatten die Erstellung bzw. Manipulation des Recordset-Objekts.
Was kommt als nächstes?
Im nächsten Kapitel erfahren Sie mehr über ASP und Datenbanken. Sie werden Microsoft Add-ons und Third-Party-Applikationen benutzen, um sich per ASP mit einer Datenbank zu verbinden.
Fragen und Antworten
Frage:
Welches sind die drei maßgeblichen Objekte in ADO? Werden diese Objekte alle von Data-Providern unterstützt?
Antwort:
Dies sind die Objekte Connection, Command und Recordset. Das Command-Objekt ist optional, da nicht alle Daten-Provider dieses Kommando zu verarbeiten in der Lage sind.
Frage:
Welches ist die beste Methode für das blinde Einfügen oder Löschen von Einträgen in eine Datenbank-Tabelle?
Antwort:
Benutzen Sie SQL-Kommandos mit der Execute-Methode. Dies spart Zeit, da Sie keinen Record-Set erstellen müssen.
Frage:
Beschreiben Sie die Charakteristiken und Anwendungsgebiete des Default-Cursors, der durch die Objekte Command und Connection erstellt wird.
Antwort:
Diese Objekte können nur Read-only- und Forward-only-record-Sets erzeugen.
Frage:
Welche Funktion bedienen die optionalen Options-Argumente der Methoden Execute und Open?
Antwort:
Das explizite Spezifizieren des Kommando-Typs im Options-Argument erspart dem Daten-Provider eine Menge Rechenarbeit.
Aufgaben
1. Lösen Sie das Problem verschiedener Einträge in findme.asp, und lassen Sie sich mehr als nur Ihre Besuchernummer anzeigen. Benutzen Sie mehr Formular-Felder, um Ihre Suche einzugrenzen. Sie könnten einen Filter anstelle eines SQL-Statements verwenden.
2. Erweitern Sie filter.asp um mehrere Filter. Falls Sie möchten, können Sie Aufgabe 1 und 2 miteinander kombinieren.
3. Erweitern Sie paramfindme.asp so, daß die Suchroutine mehr als einen Parameter zuläßt.
Ein Imprint des Markt&Technik Buch- und Software-Verlag GmbH