Das Dictionary Objekt - Dein Feind und Helfer
Geschrieben von: Christoph Wille Eine Komponente, die ein Schattendasein fristet (beziehungsweise gefristet hat) ist das Dictionary Objekt. Dabei kann es sehr nützlich sein. Wer PERL kennt, kennt die assoziativen Arrays - genau das ist ein Dictionary. Für die, die PERL nicht kennen und sich unter einem assoziativen Array nichts vorstellen können, hier die Kurzfassung: ein Schlüsselwert wird verwendet um einen zugewiesenen Wert aufzufinden (zB: eine nette Assoziation ist Flensburg und Polizei). Also gleich mal zu einem Beispiel zum leichteren Verständnis: Set myDictionary = CreateObject("Scripting.Dictionary") myDictionary.Add "Flensburg", "Polizei" myDictionary.Add "Kuba", "Zigarren"Damit erstelle ich die Assoziation, die ich dann verwenden kann, um das Teil wieder aufzusuchen: Response.Write myDictionary.Item("Flensburg")Das Resultat ist wie nicht anders zu erwarten - "Polizei". Vernünftigere Anwendungen wären Benutzername zu Paßwort Zuweisungen oder das Auslesen von Daten aus Tabellen (Primärschlüssel zugewiesen auf zB Nachname). Damit sind wir auch schon beim Thema, das Verwenden von Dictionaries zusammen mit Recordsets. Da gibt es nämlich eine unheilige Allianz, die ich anhand des folgenden Beispiels erklären werde (ich verwende die pubs Datenbank eines SQL 7 Servers names TOPGUN): <% Dim oConn, oRS, dicAuthors Set oConn = CreateObject("ADODB.Connection") oConn.ConnectionString = "provider=sqloledb.1;user id=sa;" & _ "password=;initial catalog=pubs;data source=TOPGUN" oConn.Open Set oRS = CreateObject("ADODB.Recordset") oRS.ActiveConnection = oConn oRS.Open "SELECT au_id, au_lname FROM authors" Set dicAuthors = CreateObject("Scripting.Dictionary") while not oRS.EOF dicAuthors.Add oRS(0), oRS(1) oRS.MoveNext wend oRS.Close oConn.Close Dim myKeys, myValues, i myKeys = dicAuthors.Keys myValues = dicAuthors.Items For i = 0 To (dicAuthors.Count -1) Response.Write myKeys(i) & " " & myValues(i) Next %>Eigentlich nichts besonders - außer daß ich statt über ODBC direkt über den OLE-DB Treiber auf den SQL Server zugreife (bringt Geschwindigkeit, weil der ODBC Layer ausgeschaltet wird). Der eigentliche Haken an der Geschichte ist die while-Schleife: while not oRS.EOF dicAuthors.Add oRS(0), oRS(1) oRS.MoveNext wendWenn ich das so laufen lasse, dann bekomme ich folgende Fehlermeldung: Microsoft VBScript runtime error '800a01c9' This key is already associated with an element of this collection /ASPGERMAN/dictionary2recordset.asp, line 21Analyse: Der Fehler tritt bei der zweiten Datensatzzeile auf; der Primärschlüssel au_id ist aber eindeutig - was also ist da passiert? Der Grund liegt im Dictionary selbst - ich kann Objekte zuweisen, und zwar auf den Schlüssel und den Wert (da wird die Adresse und nicht der Wert des Objekts gespeichert). Da ADO aber für oRS.Fields(0) immer das gleiche Field Objekt liefert, ist dessen Adresse im Speicher immer die gleiche - und somit ist beim 2ten Durchlauf der Fehler vorprogrammiert. Der Fehler läßt sich aber leicht beheben: dicAuthors.Add CStr(oRS(0)), oRS(1) Damit weise ich den Wert des Objekts (ein String) statt der Adresse des Objekts zu. Wenn ich das Skript jetzt laufen lasse, wird der Fehler allerdings noch um einiges lustiger, und zwar tritt er in der 2ten Zeile des folgenden Codes auf: For i = 0 To (dicAuthors.Count -1) Response.Write myKeys(i) & " " & myValues(i) NextUnd die Fehlermeldung schulde ich Euch noch: error '80020009' Exception occurred. /ASPGERMAN/dictionary2recordset.asp, line 32Ich hoffe, einige haben das mit der Objektadresse aufmerksam gelesen - ich habe gesagt, Schlüssel und Wert können ein Objekt aufnehmen, und genau das mache ich immer noch - der Wert ist oRS.Fields(1), mit dem Haken, daß ich das Recordset schon geschlossen habe. Damit ist das Field Objekt schon gelöscht, und wenn ich zugreife, bekomme ich die Zugriffsverletzung. Auch dieser Fehler läßt sich mit der bekannten Methode beseitigen: dicAuthors.Add CStr(oRS(0)), CStr(oRS(1)) Was wäre passiert, wenn das Recordset noch nicht geschlossen gewesen wäre? Ich hätte einen einzigen Wert bekommen, und zwar den, der in der letzten Zeile gestanden ist. Selbstversuch! Die Moral von der Geschichte? Dictionaries sind ein mächtiges Werkzeug - sie nehmen alles auf (inklusive Objekten), wie man dann an die Daten wieder herankommt sollte man sich aber bereits vorher überlegt haben. Die Fehler können gemein schwer zu finden sein! Verwandte Artikel
Allgemeine MailParser-Klasse mit ASPMail Wenn Sie jetzt Fragen haben...Wenn Sie Fragen rund um die in diesem Artikel vorgestellte Technologie haben, dann schauen Sie einfach bei uns in den Community Foren der deutschen .NET Community vorbei. Die Teilnehmer helfen Ihnen gerne, wenn Sie sich zur im Artikel vorgestellten Technologie weiterbilden möchten. Haben Sie Fragen die sich direkt auf den Inhalt des Artikels beziehen, dann schreiben Sie dem Autor! Unsere Autoren freuen sich über Feedback zu ihren Artikeln. Ein einfacher Klick auf die Autor kontaktieren Schaltfläche (weiter unten) und schon haben Sie ein für diesen Artikel personalisiertes Anfrageformular.
Und zu guter Letzt möchten wir Sie bitten, den Artikel zu bewerten. Damit helfen Sie uns, die Qualität der Artikel zu verbessern - und anderen Lesern bei der Auswahl der Artikel, die sie lesen sollten.
©2000-2006 AspHeute.com |