Galileo Computing < openbook >
Galileo Computing - Programming the Net
Galileo Computing - Programming the Net


Einstieg in ASP.NET von Matthias Lohrer
Einstieg in ASP.NET
gp Kapitel 12 ASP.NET und Datenbanken
  gp 12.1 Auf Datenbanken zugreifen – ein Crashkurs
    gp 12.1.1 Eine Tabelle im Browser anzeigen
    gp 12.1.2 Über den Browser einen Datensatz hinzufügen
  gp 12.2 Wie ADO.NET funktioniert – ein Überblick
  gp 12.3 Die Verbindung zur Datenbank herstellen
    gp 12.3.1 OleDbConnection
    gp 12.3.2 SqlConnection
  gp 12.4 Daten lesen mit SqlCommand und OleDbCommand
    gp 12.4.1 ExecuteReader
    gp 12.4.2 ExecuteNonQuery und die Parameters-Collection
    gp 12.4.3 ExecuteScalar
  gp 12.5 SqlDataReader und OleDbDataReader
    gp 12.5.1 Ein Reader-Objekt an ein Steuerelement binden
    gp 12.5.2 Ein Reader-Objekt an ein Listensteuerelement binden
    gp 12.5.3 Ein Reader-Objekt zeilenweise auswerten
  gp 12.6 Die DataSet-Klasse
    gp 12.6.1 Das Zusammenspiel von Command, Adapter und DataSet
    gp 12.6.2 Mehrere Tabellen in ein DataSet-Objekt einlesen
    gp 12.6.3 Auf einzelne Zeilen, Spalten und Tabellen eines DataSet-Objekts gezielt zugreifen
    gp 12.6.4 Relationen zwischen Tabellen festlegen
  gp 12.7 DataViews verwenden
    gp 12.7.1 Tabellen sortieren
    gp 12.7.2 Tabellen nach Inhalten filtern
    gp 12.7.3 Nach dem Zeilenstatus filtern
    gp 12.7.4 In Tabellen suchen
  gp 12.8 Mit ASP.NET Daten bearbeiten
  gp 12.9 Daten bearbeiten mit dem Command-Objekt
  gp 12.10 In-Place-Editing mit dem DataGrid-Steuerelement
    gp 12.10.1 Die EditItemIndex-Eigenschaft
    gp 12.10.2 Das asp:DataGrid-Tag anpassen
    gp 12.10.3 OnEditCommand: Daten bearbeiten
    gp 12.10.4 OnCancelCommand: Die Bearbeitung abbrechen
    gp 12.10.5 OnUpdateCommand: Die Änderungen sichern
    gp 12.10.6 Das Repeater-Steuerelement verwenden
    gp 12.10.7 Die Ereignisse des Repeater-Steuerelements auswerten
  gp 12.11 Das DataList-Steuerelement
    gp 12.11.1 In-Place-Editing mit dem DataList-Steuerelement


Galileo Computing

12.5 SqlDataReader und OleDbDataReader  downtop

Die Reader-Klassen SqlDataReader und OleDbDataReader liefern einen Strom von Datenbankzeilen, den Sie vorwärts gerichtet durchlaufen können. Sie sollten auch wissen, was Sie mit den Reader-Objekten nicht machen können:

gp  Sie können einen bestimmten Datensatz nicht gezielt anspringen.
gp  Sie können die Ergebnismenge nicht rückwärts durchlaufen.
gp  Sie können die Daten in der Datenbank nicht ändern.

Sie können lediglich das Ergebnis von vorn bis hinten lesen und die Daten dabei beispielsweise in irgendeiner Form ausgeben. Für alle Aufgaben, bei denen das nicht reicht, müssen Sie die DataSet-Klasse verwenden, die in Abschnitt 12.6, die DataSet-Klasse, vorgestellt wird. Der Vorteil dieser vergleichsweise »dummen« Reader-Klassen liegt in ihrer Effizienz. Diese Klassen können nicht viel. Aber das Wenige, was sie können, nämlich Daten aus einer Datenbank auslesen, wird oft benötigt. Deswegen gibt es diese entsprechend spezialisierten und optimierten Klassen.


Galileo Computing

12.5.1 Ein Reader-Objekt an ein Steuerelement binden  downtop

Das Skript db_01.aspx in Abschnitt 12.1, Auf Datenbanken zugreifen – ein Crashkurs, hat bereits einen einfachen und zugleich sehr effizienten Umgang mit dem OleDbDataReader-Objekt demonstriert. Wenn Sie ein OleDbDataReader-Objekt an ein Listensteuerelement binden, müssen Sie sich nicht mehr um die Details der Darstellung kümmern. In db_01.aspx übernimmt die Zeile myGrid.DataSource = myDataReader die Datenbindung. Hier noch einmal im Zusammenhang:

   ' ...
   ' SQL-Kommando erstellen und ausführen
   Dim sql As String
   sql = "SELECT * FROM Versandfirmen"
   Dim cmd As New OleDbCommand(sql, conn)
   Dim myDataReader As OleDbDataReader
   myDataReader = cmd.ExecuteReader()
   
   ' SQL-Resultat an ein Steuerelement binden
   myGrid.DataSource = myDataReader
   DataBind()
   ' ...

Galileo Computing

12.5.2 Ein Reader-Objekt an ein Listensteuerelement binden  downtop

Für die gezielte Verwendung von Daten innerhalb eines Formulars können Sie statt einem DataGrid-Steuerelement auch ein Listensteuerelement verwenden. In einer Anwendung möchten Sie den Benutzer beispielsweise fragen, mit welchem Paketdienst seine Waren verschickt werden sollen. Der Anwender trifft seine Auswahl anhand von Optionsfeldern. db_05a.aspx enthält den erforderlichen Code und Abbildung 12.8 zeigt die Darstellung im Browser.

Abbildung
Hier klicken, um das Bild zu Vergrößern

Abbildung 12.8 Auch Listensteuerelemente lassen sich an Datenquellen binden.

<!-- db_05a.aspx --> 
<%@ Page Language="VB" Debug="True" Strict="True" %>
<%@ Import Namespace="System.Data" %>
<%@ Import Namespace="System.Data.OleDb" %>
<script runat="server">
Sub Page_Load (ByVal Sender As Object, _
               ByVal E As EventArgs)
   If IsPostBack Then
      ausgabe.innerText = "Ihre Auswahl: " 
      ausgabe.innerText &= Versender.SelectedItem.Text
   Else
      ' Verbindungszeichenfolge zusammensetzen
      Dim connStr As String 
      connStr = "Provider=Microsoft.Jet.OLEDB.4.0;"
      connStr += "Data Source=" _
      & "C:\ASPdotNETBuch\Listings\Nordwind.mdb;"
      ' Verbindung zur Datenbank herstellen
      Dim conn As New OleDbConnection(connStr)
      conn.Open()
   
      ' SQL-Kommando erstellen und ausführen
      Dim sql As String
      sql = "SELECT * FROM Versandfirmen"
      Dim cmd As New OleDbCommand(sql, conn)
      Dim myDataReader As OleDbDataReader
      myDataReader = cmd.ExecuteReader()
   
      ' SQL-Resultat an ein Steuerelement binden
      'myGrid.DataSource = myDataReader
      Versender.DataSource = myDataReader
      Versender.DataValueField="Firmen-Nr"
      Versender.DataTextField="Firma"
      Versender.DataBind()

      myDataReader.Close()
      conn.Close()
   End If
               
End Sub
</script>
<html><head><title>
DataValueField und DataTextField bei einem 
Listensteuerelement nutzen
</title></head>
<body>
<h3>DataValueField und DataTextField bei einem 
Listensteuerelement nutzen</h3>
<p>Mit welchem Paketdienst soll Ihre Ware 
verschickt werden?</p>
<form runat="server">
<asp:RadioButtonList runat="server" id="Versender" />
<br>
<input type="submit" value=" OK " />
<p id="ausgabe" runat="server" />
</form>
</body></html>

Wenn der Anwender eine Auswahl trifft, wird unterhalb des Formulars der gewählte Paketdienst angezeigt. Im HTML-Teil von db_05a.aspx platzieren Sie ein asp:RadioButtonList-Element mit dem id-Attribut Versender. Die Prozedur Page_Load enthält zwei Zweige. Beim ersten Laden der Seite werden die Daten für das RadioButtonList-Steuerelement zusammengetragen. Der Code ist bis zur Zeile myDataReader = cmd.ExecuteReader() identisch mit dem bisherigen Vorgehen. Anschließend wird nicht myGrid, sondern Versender mit Daten bestückt. Dafür sorgen diese vier Zeilen:

Versender.DataSource = myDataReader
Versender.DataValueField="Firmen-Nr"
Versender.DataTextField="Firma"
Versender.DataBind()

Die Zuweisung an Versender.DataSource entspricht der bisherigen Zuweisung an myGrid.DataSource. Die Zuweisungen an DataValueField und DataTextField legen noch genauer fest, welche Daten wohin kommen. DataValueField nennt die Spalte für das value-Attribut des Optionsfeldes und DataTextField nennt die Spalte für die Beschriftung des Optionsfeldes. Ein Blick auf den generierten HTML-Code verdeutlicht die Arbeitsweise.

<input id="Versender_4" type="radio" name="Versender" value="3" checked="checked" />
<label for="Versender_4">Federal Shippings</label>

Der Versender mit der Firmen-Nr. 3 (value="3") heißt Federal Shippings.


Galileo Computing

12.5.3 Ein Reader-Objekt zeilenweise auswerten  toptop

Sie können die Abfrageergebnisse aber auch Zeile für Zeile und Spalte für Spalte selbst auswerten. db_06.aspx demonstriert, wie Sie mit Hilfe der Read()-Methode alle Zeilen der Ergebnismenge schrittweise durchlaufen können.


Tipp   Der Datensatzzeiger steht vor dem ersten Aufruf von Read() vor dem ersten Datensatz. Also können Sie mit While myReader.Read() bequem alle Datensätze durchlaufen.

Die Prozedur verwendet die Methode GetString(), um den Inhalt der Tabellenzeile auszulesen. Als Parameter übergeben Sie der Methode GetString() die Ordinalzahl der gewünschten Spalte zur Basis 0. Mit myString = myReader.GetString(1) lesen Sie den Inhalt der zweiten Spalte in die String-Variable myString ein. Die Voraussetzung für die Verwendung von GetString() ist übrigens, dass die Datenbankspalte selbst auch vom Typ String sein muss. Für andere Datentypen stellt die Klasse OleDbDataReader weitere Methoden wie GetInt32(), GetDouble(), GetDateTime() oder das universal verwendbare GetValue() zur Verfügung. Abbildung 12.9 zeigt das Ergebnis im Browser.

Abbildung
Hier klicken, um das Bild zu Vergrößern

Abbildung 12.9 Mit der Read()-Methode durchlaufen Sie schrittweise alle Datensätze.

<!-- db_06.aspx --> 
<%@ Page Language="VB" Debug="True" Strict="True" %>
<%@ Import Namespace="System.Data" %>
<%@ Import Namespace="System.Data.OleDb" %>
<script runat="server">
Sub Page_Load (ByVal Sender As Object, _
               ByVal E As EventArgs)
   ' Verbindungszeichenfolge zusammensetzen
   Dim connStr As String 
   connStr = "Provider=Microsoft.Jet.OLEDB.4.0;"
   connStr += _
  "Data Source=E:\ASPdotNETBuch\Listings\Nordwind.mdb;"

   ' Verbindung zur Datenbank herstellen
   Dim conn As New OleDbConnection(connStr)
   conn.Open()
   
   ' SQL-Kommando erstellen und ausführen
   Dim sql As String
   sql = "SELECT * FROM Versandfirmen"
   Dim cmd As New OleDbCommand(sql, conn)
   Dim myReader As OleDbDataReader
   myReader = cmd.ExecuteReader()

   Dim sb As New StringBuilder()
   sb.Append ("Unsere Versandfirmen: <ul>")
   
   ' Die Ergebnisse des Reader-Objekts manuell
   ' verarbeiten
   While myReader.Read()
      sb.Append ("<li>")
      sb.Append (myReader.GetString(1))
   End While
   sb.Append ("</ul>")
   ausgabe.innerHtml = sb.toString()
   
   myReader.Close()
   conn.Close()
               
End Sub
</script>
<html><head><title>
Das OleDbDataReader-Objekt verwenden
</title></head>
<body>
<h3>Das OleDbDataReader-Objekt verwenden</h3>
<p runat="server" id="ausgabe" />
</body></html>

Die Routine setzt beim Durchlaufen der While-Schleife im StringBuilder-Objekt den HTML-Code zusammen. Der Ausdruck myReader.GetString(1) gibt jeweils den Inhalt der zweiten Spalte als String-Objekt zurück.


Achtung   Diese Schleife funktioniert nur dann problemlos, wenn die Spalte mit den Firmennamen auch stets einen Eintrag enthält. Bei einem leeren Feld tritt ein Fehler auf.

Den Fall können Sie testen, indem Sie in der von Ihnen verwendeten Nordwind-Datenbank einen Datensatz mit einer weiteren Versandfirma hinzufügen und dabei das Feld Firma leer lassen. Setzen Sie vorher in der Nordwind-Datenbank in der Entwurfsansicht für die Tabelle Versandfirmen für das Feld Firma die Eigenschaft Eingabe erforderlich auf Nein.

Wenn Sie einen Datensatz mit leerem Firmennamen hinzugefügt haben, generiert die Seite beim erneuten Aufruf diese Fehlermeldung:

Die angegebene Umwandlung ist ungültig

Auslöser ist die Zeile

sb.Append (myReader.GetString(1))

Die Umwandlung eines leeren Feldes in einen String scheitert. Für solche Fälle sollten Sie mit der Methode IsDBNull() zunächst überprüfen, ob die Spalte leer ist. Damit erhält die Schleife diese Form (db_06a.aspx):

   While myReader.Read()
      If Not myReader.IsDBNull(1) Then
        sb.Append ("<li>")
        sb.Append (myReader.GetString(1))
      End If
   End While

db_07.aspx demonstriert die Verwendung einiger weiterer Eigenschaften und Methoden der Reader-Klasse. Die Methode GetDataTypeName nennt den Datentyp, den die Datenbank verwendet. GetFieldType nennt den Datentyp, den .NET für das Feld vorgesehen hat. Da die Schleife, die die Tabellenspalten durchläuft, auf unterschiedliche Datentypen trifft, verwendet die Prozedur für das Auslesen die Methode GetValue() und konvertiert das zurückgegebene Objekt vom Typ Object anschließend mit toString() in einen String. Abbildung 12.10 zeigt die Darstellung von db_07.aspx im Browser.

Abbildung
Hier klicken, um das Bild zu Vergrößern

Abbildung 12.10 GetDataTypeName nennt den Datentyp, den die Datenbank verwendet. GetFieldType nennt den .NET-Datentyp.

<!-- db_07.aspx --> 
<%@ Page Language="VB" Debug="True" Strict="True" %>
<%@ Import Namespace="System.Data" %>
<%@ Import Namespace="System.Data.OleDb" %>
<script runat="server">
Sub Page_Load (ByVal Sender As Object, _
               ByVal E As EventArgs)
   ' Verbindungszeichenfolge zusammensetzen
   Dim connStr As String 
   connStr = "Provider=Microsoft.Jet.OLEDB.4.0;"
   connStr += _
  "Data Source=E:\ASPdotNETBuch\Listings\Nordwind.mdb;"

   ' Verbindung zur Datenbank herstellen
   Dim conn As New OleDbConnection(connStr)
   conn.Open()
   
   ' SQL-Kommando erstellen und ausführen
   Dim sql As String
   sql = "SELECT * FROM Versandfirmen"
   Dim cmd As New OleDbCommand(sql, conn)
   Dim myReader As OleDbDataReader
   myReader = cmd.ExecuteReader()

   Dim sb As New StringBuilder()
   sb.Append ("Anzahl der Spalten: ")
   sb.Append (myReader.FieldCount)
   sb.Append ("<br><table border='1'>")

   Dim i As Integer
   
   ' Die Namen der Spalten ermitteln
   sb.Append ("<tr><td>Spaltennamen</td>")
   For i = 0 to myReader.FieldCount -1
      sb.Append ("<td>")
      sb.Append (myReader.GetName(i))
      sb.Append ("</td>")
   Next
   sb.Append ("</tr>")
   
   ' Datentyp mit GetDataTypeName
   sb.Append ("<tr><td>Datentyp mit GetDataTypeName</td>")
   For i = 0 to myReader.FieldCount -1
      sb.Append ("<td>")
      sb.Append (myReader.GetDataTypeName(i))
      sb.Append ("</td>")
   Next
   sb.Append ("</tr>")
      
   ' Datentyp mit GetFieldType
   sb.Append ("<tr><td>Datentyp mit GetFieldType</td>")
   For i = 0 to myReader.FieldCount -1
      sb.Append ("<td>")
      sb.Append (myReader.GetFieldType(i))
      sb.Append ("</td>")
   Next
   sb.Append ("</tr>")
   
   ' Die Tabellenzeilen auslesen    
   While myReader.Read()
      sb.Append ("<tr><td></td>")       
      for i = 0 to myReader.FieldCount -1
         If myReader.IsDBNull(i) Then
            sb.Append ("<td></td>")
         Else
            sb.Append ("<td>")
            sb.Append (myReader.GetValue(i).toString())
            sb.Append ("</td>")
         End If
      Next
      sb.Append ("</tr>")
   End While

   sb.Append ("</table>")

   ausgabe.innerHtml = sb.toString()   
   myReader.Close()
   conn.Close()
               
End Sub
</script>
<html><head><title>
Das OleDbDataReader-Objekt verwenden
</title></head>
<body>
<h3>Das OleDbDataReader-Objekt verwenden</h3>
<p id="ausgabe" runat="server" />
</body></html>

Die Klasse SqlDataReader funktioniert exakt genauso wie die Klasse OleDbDataReader. Sie fügt lediglich einige Methoden hinzu, die für die SQL-Server-typischen Datentypen optimiert sind, z. B. GetSqlDouble(), GetSqlString(), GetSqlInt32() usw.


Konstruktor: Sie erzeugen ein OleDbDataReader-Objekt über den Aufruf der ExecuteReader-Methode eines OleDbCommand-Objekts, z. B.:
myReader = myCommand.ExecuteReader()
Eigenschaften
Depth Integer Tiefe der Schachtelung für die aktuelle Zeile. Die äußerste Tabelle hat die Tiefe 0.
FieldCount Integer Anzahl der Spalten in der aktuellen Zeile
IsClosed Boolean True, wenn das Reader-Objekt geschlossen ist
Item(Integer)
oder
Item(String)
Object Default-Eigenschaft. Der Wert der angegebenen Spalte. Sie geben entweder den Spaltennamen oder die Spaltenordnungszahl an.
RecordsAffected Integer Die Anzahl der Zeilen, die von der ausgeführten SQL-Anweisung betroffen waren. Sollte erst nach dem Schließen des Reader-Objekts aufgerufen werden
Methoden
Close() Schließt das Objekt
GetBoolean
(Integer)
Boolean Gibt den Wert der angegebenen Spalte (nullbasiert) als logischen Wert an. Die Spalte muss bereits über ein logisches Format verfügen. Es werden keine Konvertierungen ausgeführt.
Für alle Get...-Methoden gilt: Vor Aufruf der Methode sollte mit IsDBNull überprüft werden, ob NULL-Werte vorhanden sind.
GetByte
(Integer)
Byte Der Wert der Spalte als einzelnes Byte
GetBytes(...) Long Liest beginnend am angegebenen Pufferoffset einen Stream von Bytes aus dem angegebenen Spaltenoffset als Array in den Puffer
GetChar(Integer) Char Wert der Spalte als Char-Objekt
GetChars(...) Long Liest beginnend am angegebenen Pufferoffset einen Stream von Zeichen aus dem angegebenen Spaltenoffset in den Puffer eines Arrays
GetDataTypeName(Integer) String Name des Quelldatentyps
GetDateTime(Integer) DateTime Wert der Spalte als DateTime-Objekt
GetDecimal
(Integer)
Decimal Wert der Spalte als Decimal-Objekt
GetDouble
(Integer)
Double Wert der Spalte als Typ Double
GetFieldType
(Integer)
Type Der Typ, der den Datentyp des Objekts darstellt
GetFloat(Integer) Single Wert der Spalte als Gleitkommazahl einfacher Genauigkeit
GetGuid(Integer) Guid Wert der Spalte als GUID (Globally Unique Identifier)
GetInt16(Integer) Short Wert der Spalte als 16-Bit-Ganzzahl mit Vorzeichen
GetInt32(Integer) Integer Wert der Spalte als 32-Bit-Ganzzahl mit Vorzeichen
GetInt64(Integer) Long Wert der Spalte als 64-Bit-Ganzzahl mit Vorzeichen
GetName(Integer) String Der Name der Spalte
GetOrdinal
(String)
Integer Nennt die zum Spaltennamen gehörige Ordinalzahl
GetSchemaTable() DataTable Ein DataTable-Objekt, das die Spalten-Metadaten des OleDbDataReader-Objekts beschreibt
GetString
(Integer)
String Wert der Spalte als String
GetTimeSpan(Integer) TimeSpan Wert der Spalte als TimeSpan-Objekt
GetValue(Integer) Object Wert der Spalte im systemeigenen Format
GetValues
(Object())
Integer Alle Attributspalten der aktuellen Zeile
IsDBNull(Integer) Boolean True, wenn die Spalte keinen Wert enthält
NextResult() Boolean Setzt den Datenleser beim Lesen der Ergebnisse von SQL-Batchanweisungen auf das nächste Ergebnis
Read() Boolean True, wenn weitere Datensätze vorhanden sind, sonst False (While myReader.Read() ...)

Tabelle 12.4 Steckbrief der Klasse OleDbDataReader

  

Einstieg in VB.NET

VB.NET

Einstieg in C#

Visual C#

VB.NET und Datenbanken

Einstieg in XML




Copyright © Galileo Press GmbH 2003
Für Ihren privaten Gebrauch dürfen Sie die Online-Version natürlich ausdrucken. Ansonsten unterliegt das <openbook> denselben Bestimmungen, wie die gebundene Ausgabe: Das Werk einschließlich aller seiner Teile ist urheberrechtlich geschützt. Alle Rechte vorbehalten einschließlich der Vervielfältigung, Übersetzung, Mikroverfilmung sowie Einspeicherung und Verarbeitung in elektronischen Systemen.


[Galileo Computing]

Galileo Press GmbH, Gartenstraße 24, 53229 Bonn, Tel.: 0228.42150.0, Fax 0228.42150.77, info@galileo-press.de