Glengamoi (Forum) · AspHeute · .NET Heute (RSS-Suche) · AspxFiles (Wiki) · .NET Blogs
ASP German Homepage Homepage
 

Liste

.NET 2.0 (1)
.NET Allgemein (16)
.NET Fu (5)
ADO.NET (11)
Aprilscherz (3)
ASP Grundlagen (44)
ASP Tricks (83)
ASP.NET (44)
ASPIntranet.de (5)
C# (28)
Datenbank (44)
Dokumentation (4)
IIS 6.0 (1)
Komponenten (29)
Optimierung (10)
Server (21)
Sicherheit (34)
Tee Off (6)
VB.NET (6)
WAP (8)
Web Services (11)
XML (9)

RSS 2.0 - Die neuesten fünf Artikel auf AspHeute.com


 

Suchen





 

English Articles
Chinese Articles
Unsere Autoren
 
Link zu AspHeute
Impressum
Werben
Anfragen

Auto-Generierung von performantem Abfragecode

Geschrieben von: Christian Holm
Kategorie: Datenbank

Dieser Artikel zeigt Ihnen wie man mit Hilfe eines server-seitigen Code Generators eine Datenbankabfrage erstellt, die einiges an Performance bietet. Der Code Generator ist dabei unabhängig von der Struktur der Datenbank. Den generierten Code können Sie danach als ASP-Datei abspeichern - und er ist sofort einsatzbereit.

Der Code Generator übernimmt lediglich zwei Werte - den Connection String und den für die Abfrage notwendigen Query String - die Arbeit erledigt der Generator. Das Interface ist von der Struktur her dasselbe wie aus dem Artikel Code Generator für die AddNew Methode. Deshalb will ich heute auch nur das Kernstück des ASP-Scripts - die einzelnen Functions des Generators - besprechen.

Als Testumgebung habe ich die MS Internet Information Services in der Version 5 und den MS SQL Server 2000 verwendet. Die Testdatenbank ist wieder einmal Northwind. Der Generator aber funktioniert mit Access oder anderen Datenbanken ebenso.

Um den ASP Code für die Datenbankabfrage zu erstellen besitzt der Generator mehrere VBScript Funktionen, die ich Ihnen im einzelnen nun vorstellen werde, und wir beginnen mit der Hauptfunktion: GenerateCode.

Die GenerateCode Funktion

Diese Funktion erledigt die Generierung des notwendigen ADO/ASP Codes. Zuerst werden die für die Abfrage erforderlichen Codezeilen in die Ausgabevariable strOutput geschrieben.

Function GenerateCode(ByVal strConn, ByVal strSQLStmt)
 Dim strOutput, objRS, fld, strFieldObjects
 strOutput =  WriteMetadata() & vbCrlf & "<" & "%" & vbCrlf
 strOutput = strOutput & "Set objRS = Server.CreateObject(""ADODB.Recordset"")" & vbCrlf
 strOutput  = strOutput & "strSQLStmt = """ & strSQLStmt & """" & vbCrlf
 strOutput  = strOutput & "strConn = """ & strConn & """" & vbCrlf
 strOutput  = strOutput & "objRS.CursorLocation = adUseClient" & vbCrlf
 strOutput  = strOutput & "objRS.CursorType = adOpenStatic" & vbCrlf
 strOutput  = strOutput & "objRS.LockType = adLockBatchOptimistic" & vbCrlf
 strOutput  = strOutput & "objRS.Open strSQLStmt, strConn" & vbCrlf
 strOutput  = strOutput & "Set objRS.ActiveConnection = Nothing" & vbCrlf

Der generierte Code beginnt mit der Funktion WriteMetadata, die uns, wie später genauer gezeigt, die ADO Konstanten mittels eines METADATA Statements einbindet. Danach geht es weiter mit der Initialisierung des Recordset Objekts - um die höchste Performance zu erhalten, lege ich ein client-seitiges (disconnected) Recordset an, das ich sofort nach Aufruf der Open Methode von der Datenquelle trennen kann (ActiveConnection = Nothing). Dadurch wird der SQL Server sofort entlastet, und ich kann so lange (oder langsam) mit den Daten weiterarbeiten, wie es mir Freude macht.

Im nächsten Abschnitt wird der Code erstellt, der für die Ausgabe der einzelnen Records verantwortlich ist. Dies geschieht aber nicht auf die herkömmliche Art und Weise. Denn ich erstelle eine Objektreferenz auf jede Spalte (repräsentiert durch ein Field Objekt), die es mir erlaubt, später ohne Zugriff auf die Fields Collection auszukommen. In einer While Schleife mit hunderten Records bringt diese Art der Programmierung einiges an Performance zusätzlich.

Set objRS = Server.CreateObject("ADODB.Recordset")
objRS.Open strSQLStmt, strConn
 
 strOutput = strOutput & vbCrlf & "If Not objRS.EOF Then" & vbCrLf
 For Each fld in objRS.Fields
   strFieldObjects = strFieldObjects & "  Set obj" & GenerateFieldname(fld.Name)
   strFieldObjects = strFieldObjects & " = objRS.Fields(""" & fld.Name & """)" & vbCrlf
 Next
 strOutput = strOutput & strFieldObjects
 strOutput = strOutput & "End If" & vbCrLf & vbCrlf

Die Generierung der Referenzen ist in einer If Bedingung geschachtelt - was ist, wenn keine Records zur Laufzeit geliefert werden? Wozu sollte ich Zeit verschwenden, Referenzen zu legen, die dann sowieso niemand verwendet. Für die Referenz benötige ich einen sinnvollen, eindeutigen Objektnamen. Diesen erstelle ich mit der GenerateFieldname Function, der ich den Namen der SQL Spalte aus dem Recordset übergebe. Sie ist verantwortlich, in VBScript Variablennamen nicht verträgliche Spaltennamen zu "korrigieren" - derzeit behandle ich nur das Leerzeichen.

Um auch die Verwendung der Referenzen zu verdeutlichen, ist in der abschließenden While Schleife ein auskommentiertes Beispiel mit dabei. Das sieht dann so aus:

 strOutput = strOutput & "While Not objRS.EOF" & vbCrlf
 strOutput = strOutput & "   ' SAMPLE CODE: Response.Write(objFieldname.Value)" & vbCrlf
 strOutput = strOutput & "   objRS.MoveNext" & vbCrlf
 strOutput = strOutput & "Wend" & vbCrlf & vbCrlf

 strOutput = strOutput & "Set objRS = Nothing" & vbCrlf

 strOutput = strOutput & "%" & ">" & vbCrlf
 GenerateCode = strOutput
End Function

Damit hätten wir die GenerateCode Funktion fertig durchbesprochen - jetzt zeige ich Ihnen noch, wie die in GenerateCode verwendeten Hilfsfunktionen Ihre Arbeit verrichten. Beginnen wir mit der GenerateFieldname Funktion.

Die GenerateFieldname Funktion

Da wie schon erwähnt der Fieldname manchmal etwas Kosmetik benötigt, da er Sonderzeichen, Leerzeichen etc. enthalten kann, erledige ich dies mit dieser Funktion. Allerdings Vorsicht - da wir keine Sonderzeichen verwenden, habe ich nur das auffälligste korrigiert, nämlich Leerzeichen - weil in der Northwind Datenbank solche vorkommen können.

Function GenerateFieldname(strSQLFieldName)
 Dim strFieldname
 strFieldname = Replace(strSQLFieldName, " ", "_")
 GenerateFieldname = strFieldname
End Function

ADO Konstanten einbinden - Mal 2

Da der generierte ASP Code ADO Konstanten verwendet, muß ich diese irgendwie definieren. Dies kann auf zwei Arten erfolgen: entweder ich inkludiere adovbs.inc, oder ich verwende ein METADATA Statement für die Type Library (der heute vorgestellte Code verwendet per Default die Typenbibliothek). Um es einfach austauschbar zu halten, habe ich die Einbindungen modular in Funktionen verpackt:

WriteAdovbsInc

Function WriteAdovbsInc()
 WriteAdovbsInc = "<" & "!-- #inc" & "lude file=""adovbs.inc"" -" & "->"
End Function

WriteMetadata

Function WriteMetadata()
  Dim strMD  
  strMD = "<" & "!--METADATA NAME=""Microsoft ActiveX Data Objects 2.5 Library"" "
  strMD = strMD & "TYPE=""TypeLib"" "
  strMD = strMD & "UUID=""{00000205-0000-0010-8000-00AA006D2EA4}""-->"
  WriteMetadata = strMD
End Function

Beide Funktionen erfüllen die Aufgabe auf gleiche Weise: sie setzen den benötigten Code aus einzelnen Fragmenten zusammen, sodaß der ASP Parser diese nicht mißinterpretiert.

Das Resultat

Wenn Sie nun den Code Generator (CodeGenSpeedyLoop.asp) auf einem Webserver ausführen, und Zugang zu einem Datenbank Server haben, erhalten Sie folgendes Resultat in einem Web Browser:

Abschließend habe ich noch, sozusagen als Funktionstest den vom Generator erstellten Code als ASP Datei abgespeichert und ebenfalls ablaufen lassen. Dabei habe ich mir den Firmennamen (CompanyName) aus der Shippers Tabelle anzeigen lassen:

<!--METADATA NAME="Microsoft ActiveX Data _
Objects 2.5 Library" TYPE="TypeLib" _
UUID="{00000205-0000-0010-8000-00AA006D2EA4}"-->

<%
Set objRS = Server.CreateObject("ADODB.Recordset")
strSQLStmt = "SELECT * FROM Suppliers"
strConn = "Provider=SQLOLEDB;server=bluescreen;uid=sa;pwd=;Initial Catalog=Northwind;"
objRS.CursorLocation = adUseClient
objRS.CursorType = adOpenStatic
objRS.LockType = adLockBatchOptimistic
objRS.Open strSQLStmt, strConn
Set objRS.ActiveConnection = Nothing

If Not objRS.EOF Then
  Set objSupplierID = objRS.Fields("SupplierID")
  Set objCompanyName = objRS.Fields("CompanyName")
  Set objContactName = objRS.Fields("ContactName")
  Set objContactTitle = objRS.Fields("ContactTitle")
  Set objAddress = objRS.Fields("Address")
  Set objCity = objRS.Fields("City")
  Set objRegion = objRS.Fields("Region")
  Set objPostalCode = objRS.Fields("PostalCode")
  Set objCountry = objRS.Fields("Country")
  Set objPhone = objRS.Fields("Phone")
  Set objFax = objRS.Fields("Fax")
  Set objHomePage = objRS.Fields("HomePage")
End If

While Not objRS.EOF
   Response.Write(objCompanyName.Value & "<br>")
   objRS.MoveNext
Wend

Set objRS = Nothing
%>

Schlußbemerkung

Dieser (weitere) Code Generator hilft wieder dabei, lästige Schreibarbeit bei umfangreichen Datenbankaufgaben abzunehmen. Da der Generator nur den Connection- und den Query Sting übernimmt, ist er für jede beliebige Datenbankstruktur anwendbar. Obendrein wird noch ein sehr leistungsfähiger Code produziert.

Download des Codes

Klicken Sie hier, um den Download zu starten.

Verwandte Artikel

Benutzerverwaltung leicht gemacht: Teil 1
Code Generator für die AddNew Methode
Der ADO Command Code Generator
Die SQL2Table Komponente
Intelligente Meta-Tags
Optimiertes Erstellen von DropDowns
Stored Procedures einfach erstellt

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.

Bewerten Sie diesen Artikel
 Sehr gut   Nicht genügend  
   1  2  3  4  5  
 

  
   Für Ausdruck optimierte Seite

©2000-2006 AspHeute.com
Alle Rechte vorbehalten. Der Inhalt dieser Seiten ist urheberrechtlich geschützt.
Eine Übernahme von Texten (auch nur auszugsweise) oder Graphiken bedarf unserer schriftlichen Zustimmung.