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.6 Die DataSet-Klasse  downtop

Wenn es lediglich um das Lesen von Daten geht, sind Sie mit den Klassen OleDbDataReader oder SqlDataReader bestens bedient. Für die Bearbeitung von Daten stellt .NET die Klasse DataSet zur Verfügung.

Die DataSet-Klasse steht im Mittelpunkt der gesamten ADO.NET-Architektur. Folgende Aussagen treffen auf ein DataSet-Objekt zu:

gp  Ein DataSet-Objekt kann mehrere Tabellen enthalten. Zu den Tabellen können Relationen und einschränkende Bedingungen gespeichert sein. Damit kann ein DataSet-Objekt die Daten einer kompletten relationalen Datenbank aufnehmen.
gp  Ein DataSet-Objekt weiß nicht, woher die Daten stammen, die in ihm gespeichert sind. Die Daten können aus einer relationalen Datenbank oder aus einer XML-Datei stammen, oder sie wurden im Arbeitsspeicher zusammengesetzt.
gp  Ein DataSet-Objekt hält keine permanente Verbindung zu seiner Datenquelle geöffnet. Beim Anlegen eines DataSet-Objekts werden die Daten in einem Rutsch in das DataSet-Objekt geschrieben und die Verbindung zur Datenquelle wird anschließend wieder geschlossen. Bearbeitungsschritte erfolgen ausschließlich an diesem DataSet-Objekt, das im Arbeitsspeicher liegt. Erst auf eine ausdrückliche Anweisung hin werden die Änderungen in die Datenquelle zurückgeschrieben. Ein DataSet-Objekt arbeitet im Prinzip also wie ein Datencache, die Zeilen einer Tabelle verfügen daher über einen Zeilenstatus. Der Zeilenstatus markiert eine Zeile als unverändert/bearbeitet/gelöscht usw.

Bei der Arbeit mit DataSet-Objekten kommen Sie mit einer ganzen Palette von weiteren Klassen in Berührung.

gp  Das Command-Objekt haben Sie bereits kennen gelernt. Auch im Zusammenspiel mit einem DataSet-Objekt legen Sie mit einem Command-Objekt fest, welche Daten Sie in das DataSet-Objekt einlesen wollen.
gp  Den Zugriff auf die Datenquelle führt ein Objekt vom Typ OleDbDataAdapter oder SqlDataAdapter durch. Einem solchen Adapter-Objekt übergeben Sie das Command-Objekt. Anschließend kann das Adapter-Objekt mit der Fill-Methode die per Command-Objekt beschriebenen Daten in das DataSet-Objekt einfüllen.

Da ein DataSet-Objekt die Daten einer ganzen Datenbank aufnehmen kann, gibt es weitere Klassen für die einzelnen Bestandteile.

gp  E DataTable-Objekte nehmen einzelne Tabellen auf.
gp  Die Spalten und Zeilen einer Tabelle werden durch DataColumn- und DataRow-Objekte dargestellt.
gp  Relationen zwischen Tabellen werden in DataRelation-Objekten festgehalten.
gp  Bedingungen für den Erhalt der Datenintegrität werden durch Constraint-Objekte festgelegt.
gp  Für das Sortieren, Filtern, Durchsuchen und Bearbeiten von Daten verwenden Sie DataView-Objekte.

Galileo Computing

12.6.1 Das Zusammenspiel von Command, Adapter und DataSet  downtop

Die erste DataSet-Etüde soll das Gleiche leisten wie db_01.aspx. Der Inhalt der Tabelle Versandfirmen soll an ein DataGrid-Steuerelement gebunden und im Browser angezeigt werden. In fünf Schritten erreichen Sie das angestrebte Ziel:

1. Sie erstellen ein Command-Objekt mit dem erforderlichen SQL-Statement. Dim cmd As New OleDbCommand(sql, conn) 2. Sie erstellen einen Adapter und weisen ihm das Command-Objekt zu. Dim myAdapter As New OleDbDataAdapter()
myAdapter.SelectCommand = cmd 3. Sie erstellen ein zunächst noch leeres DataSet-Objekt. Dim myDS As New DataSet() 4. Sie füllen mit dem Adapter die im Command-Objekt definierten Daten in das DataSet-Objekt ein. myAdapter.Fill (myDS) 5. Sie binden das DataSet-Objekt an das DataGrid-Steuerelement als Datenquelle an. myGrid.DataSource = myDS
DataBind()

db_08.aspx zeigt den erforderlichen Code im Zusammenhang. Die Darstellung im Browser ist, abgesehen vom geänderten Titel, mit der Abbildung 12.1 identisch. Der Browser zeigt den Inhalt der Tabelle Versandfirmen an.

<!-- db_08.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 myAdapter As New OleDbDataAdapter()
   myAdapter.SelectCommand = cmd
   
   Dim myDS As New DataSet()
   myAdapter.Fill (myDS)
   
   myGrid.DataSource = myDS 
   DataBind()
   
   conn.Close()
               
End Sub
</script>
<html><head><title>Mit dem DataSet-Objekt Daten 
aus einer Datenbank auslesen</title></head>
<body>
<h3>Mit dem DataSet-Objekt Daten aus einer 
Datenbank auslesen</h3>
<p>Die Nordwind-Datenbank verzeichnet folgende 
Versandfirmen:</p>
<asp:DataGrid id="myGrid" runat="server" />
</body></html>

Konstruktoren
New() Konstruktor
New(OleDbCommand) Der Parameter enthält ein OleDbCommand als SelectCommand.
New (String,OleDbConnection) Die Parameter enthalten den CommandText für die SelectCommand-Eigenschaft und die OleDbConnection.
New(String, String) Die Parameter enthalten einen String für SelectCommand und eine Verbindungszeichenfolge.
Eigenschaften
DeleteCommand OleDbCommand SQL-Anweisung oder Stored Procedure, um Datensätze zu löschen
InsertCommand OleDbCommand Einfüge-Anweisung
SelectCommand OleDbCommand Auswahl-Anweisung (SELECT ...)
UpdateCommand OleDbCommand Aktualisierungs-Anweisung
Methoden
Fill(DataSet, String)
Fill(DataSet)
Fill(DataTable)
und andere
Lädt Daten in ein DataSet- oder DataTable-Objekt. Fill() kennt zahlreiche überladene Methoden mit unterschiedlichen Parametern.
Update(DataRow())
Update(DataSet)
Update(DataTable)
und andere
Ruft für jede eingefügte, aktualisierte oder gelöschte Zeile im DataSet-Objekt die INSERT-, UPDATE- bzw. DELETE-Anweisung auf

Tabelle 12.5 Steckbrief für die Klasse OleDbDataAdapter


Galileo Computing

12.6.2 Mehrere Tabellen in ein DataSet-Objekt einlesen  downtop

Als Nächstes möchten Sie mehrere Tabellen in das DataSet-Objekt übertragen. Sie erreichen das, indem Sie die Fill-Methode des OleDbDataAdapter-Objekts mehrfach mit jeweils geänderten Parametern aufrufen. Dafür reichen ein OleDbDataAdapter-Objekt und ein OleDbCommand-Objekt, die Sie jeweils entsprechend ausrüsten. db_09.aspx demonstriert den Weg.

Zunächst bereiten Sie die Verbindung vor:

   Dim conn As New OleDbConnection(connStr)
   conn.Open()

Sie bereiten ein Kommando-Objekt vor, indem Sie es auf die Verbindung beziehen.

   Dim cmd As New OleDbCommand()
   cmd.Connection = conn

Sie bereiten ein Adapter-Objekt vor und überreichen ihm das Kommando-Objekt:

   Dim myAdapter As New OleDbDataAdapter()
   myAdapter.SelectCommand = cmd

Und schließlich benötigen Sie noch das DataSet-Objekt selbst:

   Dim myDS As New DataSet()

Wenn Sie so weit sind, können Sie die benötigten SQL-Statements erstellen, dem Kommando-Objekt übergeben und die Fill-Methode des Adapter-Objekts mehrfach aufrufen. Zunächst lesen Sie die komplette Tabelle Versandfirmen ein.

   Dim sql1 As String
   sql1 = "SELECT * FROM Versandfirmen"
   cmd.CommandText = sql1
   myAdapter.Fill (myDS, "Versandfirmen")

Der Methode Fill übergeben Sie als ersten Parameter das DataSet-Objekt und als zweiten Parameter eine Bezeichnung, unter der die selektierten Daten innerhalb des DataSet-Objekts identifizierbar sein sollen. Statt des Namens der Tabelle können Sie hier auch eine beliebige andere Zeichenfolge verwenden.

Als Nächstes möchten Sie aus der Tabelle Personal lediglich die Spalten Personal-Nr, Vorname und Nachname anzeigen:

   Dim sql2 As String
   sql2 = "SELECT [Personal-Nr], Vorname, Nachname " 
   sql2 += "FROM Personal" 
   cmd.CommandText = sql2
   myAdapter.Fill (myDS, "Personal")

Der Bindestrich im Feldnamen Personal-Nr macht es erforderlich, diesen Namen innerhalb des SQL-Statements in eckige Klammern einzuschließen.

Die beiden Tabellen möchten Sie jeweils in einem eigenen DataGrid-Steuerelement anzeigen lassen. Mit der Eigenschaft Tables des DataSet-Objekts greifen Sie auf dessen DataTableCollection-Objekt zu. Die einzelnen Tabellen erreichen Sie entweder über die Ordnungszahl oder über die Namen, die Sie beim Einlesen vergeben haben.

   myGrid1.DataSource = myDS.Tables("Versandfirmen")
   myGrid2.DataSource = myDS.Tables("Personal")
   DataBind()

Zum Abschluss schließen Sie die Verbindung:

   conn.Close()

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

Abbildung 12.11 Mit mehreren Aufrufen der Fill-Methode des Adapter-Objekts übertragen Sie mehrere Tabellen in ein DataSet-Objekt.

Abbildung 12.12 zeigt die Darstellung im Browser. Hier sehen Sie noch einmal den kompletten Code im Zusammenhang.

<!-- db_09.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 herstellen
   Dim conn As New OleDbConnection(connStr)
   conn.Open()   
   ' Kommando-Objekt vorbereiten
   Dim cmd As New OleDbCommand()
   cmd.Connection = conn
   ' Adapter-Objekt vorbereiten
   Dim myAdapter As New OleDbDataAdapter()
   myAdapter.SelectCommand = cmd
   ' DataSet-Objekt vorbereiten
   Dim myDS As New DataSet()
         
   ' Tabelle "Versandfirmen" einlesen
   Dim sql1 As String
   sql1 = "SELECT * FROM Versandfirmen"
   cmd.CommandText = sql1
   myAdapter.Fill (myDS, "Versandfirmen")
   
   ' Einige Spalten aus der Tabelle "Personal" einlesen
   Dim sql2 As String
   sql2 = "SELECT [Personal-Nr], Vorname, Nachname " 
   sql2 += "FROM Personal" 
   cmd.CommandText = sql2
   myAdapter.Fill (myDS, "Personal")
   
   myGrid1.DataSource = myDS.Tables("Versandfirmen")
   myGrid2.DataSource = myDS.Tables("Personal")
   DataBind()
   
   conn.Close()
End Sub
</script>
<html><head><title>
Mehrere Tabellen in ein DataSet-Objekt einlesen
</title></head>
<body>
<h3>Mehrere Tabellen in ein DataSet-Objekt einlesen
</h3>
<asp:DataGrid id="myGrid1" runat="server" /><br>
<asp:DataGrid id="myGrid2" runat="server" />
</body></html>

Beachten Sie die Form des zweiten SQL-Statements.

   sql2 = "SELECT [Personal-Nr], Vorname, Nachname " 
   sql2 += "FROM Personal"

Hier kommt es auf die eckigen Klammern um das Feld Personal-Nr an, die wegen des Bindestrichs im Feldnamen erforderlich sind.


Achtung   Wenn Sie die eckigen Klammern weglassen, erhalten Sie die in Abbildung 12.12 gezeigte irreführende Fehlermeldung: Für mindestens einen erforderlichen Parameter wurde kein Wert angegeben. Dabei lokalisiert der Compiler die Fehlerursache in der Zeile myAdapter.Fill (myDS, "Personal"). Tatsächlich ist mit diesem Befehl aber alles in Ordnung. Auch die »erforderlichen Parameter« wurden der Fill-Methode korrekt übergeben. Wenn Sie die eckigen Klammern im SQL-Statement ergänzen, funktioniert es.

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

Abbildung 12.12 Ein fehlerhaftes SQL-Statement erzeugt diese irreführende Fehlermeldung.


Galileo Computing

12.6.3 Auf einzelne Zeilen, Spalten und Tabellen eines DataSet-Objekts gezielt zugreifen  downtop

Innerhalb eines DataSet-Objekts finden Sie die typische verschachtelte Struktur aus Tabellen, Zeilen und Spalten vor.

gp  Ein DataSet-Objekt enthält über seine Eigenschaft Tables eine DataTableCollection mit DataTable-Elementen.
gp  Ein DataTable-Objekt enthält über die Eigenschaft Columns eine DataColumnCollection und über die Eigenschaft Rows eine DataRowCollection.
gp  Eine DataRowCollection enthält Objekte vom Typ DataRow und eine DataColumnCollection enthält Objekte vom Typ DataColumn.

Mit Hilfe dieser Objekte können Sie relativ einfach auf alle Bestandteile zugreifen. db_10.aspx zeigt, wie Sie einzelne Wert oder auch den gesamten Datenbestand eines DataSet-Objekts auslesen können. Abbildung 12.13 zeigt die Darstellung im Browser. Der Code ist bis zum zweiten Aufruf der Fill-Methode mit db_09.aspx identisch.

<!-- db_10.aspx --> 
<!-- Der Code ist mit db_09.aspx bis zur ersten 
folgenden Zeile identisch:  -->
   ' ...
   myAdapter.Fill (myDS, "Personal")

   Dim myTable As DataTable
   Dim myRow As DataRow
   Dim myCol As DataColumn
   Dim sb As New StringBuilder()
   
   ' Wie viele Tabellen enthält das Dataset?
   sb.Append ("Das DataSet enthält ingesamt <b>")
   sb.Append (myDS.Tables.count)
   sb.Append ("</b> Tabellen. <br>")
   
   ' Den Wert einer einzelnen Zelle auslesen
   myRow = myDS.Tables(1).Rows(1)
   sb.Append ("Die zweite Tabelle enthält in der ")
   sb.Append ("zweiten Zeile, zweite Spalte diesen ")
   sb.Append ("Wert:<b> " & myRow(1).toString())
   sb.Append ("</b>" )
   
   ' Alle Tabellen des Datasets ausgeben
   For Each myTable in myDS.Tables
      sb.Append ("<br><br>Tabellenname: <b>" )
      sb.Append (myTable.TableName & "</b>")
      For Each myRow in myTable.Rows
         sb.Append ("<br>")
         For Each myCol in myTable.Columns
            sb.Append (myRow(myCol).toString())
            sb.Append (" ---" )
         Next myCol      
      Next myRow
   Next myTable
   
   ausgabe.innerHTML = sb.toString()
   conn.Close()
End Sub
</script>
<html><head><title>
Auf einzelne Zeilen, Spalten und Tabellen 
eines DataSet-Objekts gezielt zugreifen
</title></head>
<body>
<h3>Auf einzelne Zeilen, Spalten und Tabellen 
eines DataSet-Objekts gezielt zugreifen</h3>
<p id="ausgabe" runat="server" />
</body></html>

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

Abbildung 12.13 Mit den Klassen DataTable, DataRow und DataColumn greifen Sie gezielt auf die Bestandteile eines DataSet-Objekts zu.

Für den Zugriff auf eine einzelne Tabellenzelle verwenden Sie die Rows-Eigenschaft des DataTable-Objekts. Innerhalb eines DataRow-Objekts sprechen Sie eine einzelne Zelle anschließend entweder über die Ordinalzahl oder über den Feldnamen an. Der Ausdruck myRow(0) gibt den Inhalt des ersten Feldes zurück. myRow(1) nennt den Inhalt des zweiten Feldes usw. Hierbei kommt die mehrfach überladene Default-Eigenschaft Item zum Einsatz.


Tipp   Merken Sie sich, dass Sie für die Adressierung einer einzelnen Tabellenzelle erst die Zeile und dann die Spalte angeben. Andersherum führt kein Weg zur einzelnen Zelle. Ein DataColumn-Objekt verfügt also nicht über eine Rows-Eigenschaft oder etwas Ähnliches. Ein DataColumn-Objekt dient vorwiegend dazu, die Typmerkmale einer Spalte festzulegen.


Konstruktoren
New()
New(String)
Der Tabellenname kann übergeben werden.
Eigenschaften
CaseSensitive Boolean Gibt an, ob bei Vergleichen zwischen Zeichenfolgen die Groß- und Kleinschreibung berücksichtigt wird
ChildRelations DataRelationCollection Eine DataRelationCollection mit den untergeordneten Beziehungen für diese Tabelle
Columns DataColumnCollection Eine Auflistung von DataColumn-Objekten
Constraints ConstraintCollection Eine Auflistung von Constraint-Objekten für diese Tabelle
DataSet DataSet Das DataSet-Objekt, zu dem diese Tabelle gehört
DefaultView DataView Das zugeordnete DataView-Objekt
ExtendedProperties PropertyCollection Benutzerdefinierte Schlüssel-Wert-Paare
HasErrors Boolean Gibt an, ob eine Zeile der Tabelle Fehler enthält. Sollte vor dem Zurückschreiben überprüft werden
ParentRelations DataRelationCollection Die übergeordneten Beziehungen für diese Tabelle
PrimaryKey DataColumn() Ein Array von Spalten, die als Primärschlüssel für die Tabelle verwendet werden
Rows DataRowCollection Die Zeilen der Tabelle
TableName String Der Name der Tabelle
Methoden
AcceptChanges() Übernimmt alle Änderungen, die an dieser Tabelle seit dem letzten Aufruf von AcceptChanges vorgenommen wurden
BeginLoadData() Deaktiviert während des Ladens von Daten Benachrichtigungen, Indexverwaltung und Einschränkungen
Clear() Löscht alle Daten aus der Tabelle
Clone() Erstellt ein DataTable-Objekt mit dem gleichen Schema
Compute (expressionstring, filterstring) Berechnet den Ausdruck für alle Zeilen, die auf den Filter-Ausdruck zutreffen
Copy() Gibt ein DataTable-Objekt mit gleicher Struktur und Daten zurück
EndLoadData() Aktiviert nach dem Laden von Daten Benachrichtigungen, Indexverwaltung und Einschränkungen
GetChanges() As DataTable Gibt ein DataTable-Objekt zurück, das alle Änderungen enthält, die seit dem letzten Laden oder seit dem letzten Aufruf von AcceptChanges vorgenommen wurden
GetErrors() As DataRow() Gibt ein Array von DataRow-Objekten zurück, die Fehler enthalten
ImportRow (DataRow) Kopiert ein DataRow-Objekt in die Tabelle
LoadDataRow() Nimmt ein Array von Werten an und sucht einen oder mehrere übereinstimmende Werte in der bzw. den Primärschlüsselspalten
NewRow() As DataRow Erstellt eine neue DataRow mit dem Schema der Tabelle
RejectChanges() Nimmt alle Änderungen zurück, die an der Tabelle seit dem Laden oder seit dem letzten Aufruf von AcceptChanges vorgenommen wurden
Reset() Setzt die Tabelle in den ursprünglichen Zustand zurück
Select Ruft ein Array von DataRow-Objekten ab

Tabelle 12.6 Steckbrief der Klasse DataTable


Konstruktor
Um ein neues DataRow-Objekt zu erstellen, verwenden Sie die NewRow-Methode eines DataTable-Objekts. Die neu erstellte Zeile müssen Sie anschließend noch mit Add an die DataRowCollection anfügen. Beispiel: Dim myRow as DataRow
myRow = myTable.NewRow()
myTable.Rows.Add (myRow)
Eigenschaften
HasErrors Boolean True, wenn die Zeile Fehler enthält
Item(String)
Item(DataColumn)
Item(Integer)
Object Default-Eigenschaft. Daten der angegebenen Spalte. Die Spalte kann benannt, als Ordinalzahl oder als DataColumn-Objekt übergeben werden.
ItemArray Object() Alle Werte der Zeile in Form eines Arrays von Objekten des Typs Object
RowError String Die benutzerdefinierte Fehlerbeschreibung für eine Zeile
RowState DataRowState Der aktuelle Zustand der Zeile in Bezug auf die DataRowCollection. Mögliche Werte sind Added, Deleted, Detached, Modified und Unchanged.
Table DataTable Die Tabelle, zu der diese Zeile gehört
Methoden
AcceptChanges() Übernimmt alle Änderungen an dieser Zeile, die seit dem letzten Aufruf von AcceptChanges() vorgenommen wurden
BeginEdit() Beginnt einen Bearbeitungsvorgang für die Zeile
CancelEdit() Bricht den aktuellen Bearbeitungsvorgang ab
ClearErrors() Entfernt alle Fehler
Delete() Markiert die Zeile als gelöscht
EndEdit() Beendet den Bearbeitungsvorgang
GetChildRows(DataRelation)
GetChildRows(String)
u. a.
DataRow() Liefert für die übergebene DataRelation ein Array aus DataRow-Objekten mit den Kindzeilen
GetColumnError(DataColumn)
GetColumnError(Integer)
GetColumnError(String)
String Die Fehlerbeschreibung für eine Spalte
GetColumnsInError() DataColumn() Ein Array mit fehlerhaften Spalten
GetParentRow(DataRelation)
GetParentRow(String)
DataRow Die übergeordnete Zeile in Bezug auf die übergebene Relation
GetParentRows(DataRelation)
GetParentRows(String)
DataRow() Die übergeordnete Zeile in Bezug auf die übergebene Relation
HasVersion(DataRowVersion) Boolean True, wenn der gesuchte Bearbeitungszustand verfügbar ist. Möglich sind Current, Default, Original und Proposed.
IsNull(DataColumn)
IsNull(Integer)
IsNull(String)
IsNull(DataColumn,DataRowVersion)
Boolean True, wenn die angegebene Spalte einen NULL-Wert enthält
RejectChanges() Lehnt alle Änderungen ab, die seit dem letzten Aufruf von AcceptChanges an der Zeile vorgenommen wurden
SetColumnError(DataColumn, String)
SetColumnError(Integer, String)
SetColumnError(String, String)
Die Fehlerbeschreibung für eine Spalte
SetParentRow(DataRow)
SetParentRow(DataRow, DataRelation)
Legt die übergeordnete Zeile fest

Tabelle 12.7 Steckbrief der Klasse DataRow


Konstruktoren
New() New(String) New(String,Type) New(String,Type,String) New(String,Type,String,MappingType) Mögliche Parameter für den Konstruktor sind der Spaltenname, der Datentyp, ein Ausdruck z. B. für berechnete Spalten (entspricht der Eigenschaft Expression) und ein Wert, der bestimmt, ob die Spalte im XML-Zusammenhang als Attribut behandelt werden soll.
Eigenschaften
AllowDBNull Boolean True, wenn in der Spalte NULL-Werte zulässig sind
AutoIncrement Boolean True, wenn der Spaltenwert für neue Zeilen automatisch erhöht werden soll
AutoIncrementSeed Long Anfangswert für die AutoIncrement-Eigenschaft
AutoIncrementStep Long Der Wert, um den der Spaltenwert jeweils erhöht werden soll. Standard ist 1.
Caption String Spaltenbeschriftung. Wenn hier nichts angegeben wird, wird ColumnName verwendet.
ColumnMapping MappingType Der MappingType der Spalte. Betrifft die Darstellung im XML-Kontext
ColumnName String Der Name der Spalte in der DataColumnCollection
DataType Type Spaltentyp
DefaultValue Object Standardwert, muss dem DataType der Spalte entsprechen
Expression String Ausdruck, der Zeilen filtert, die Werte der Spalte berechnen oder eine Aggregatspalte erstellen kann
ExtendedProperties PropertyCollection Auflistung der Benutzerinformationen
MaxLength Integer Maximale Länge einer Textspalte. Keine Beschränkung wird durch den Standardwert –1 signalisiert.
Namespace String Der Namespace der DataColumn
Ordinal Integer Die Position der Spalte in der DataColumnCollection
Prefix String XML-Präfix, das als Alias für den Namespace der DataTable fungiert
ReadOnly Boolean True, wenn die Spalte schreibgesschützt ist
Table DataTable Die DataTable, zu der die Spalte gehört
Unique Boolean True, wenn alle Werte der Spalte eindeutig sein müssen

Tabelle 12.8 Steckbrief der Klasse DataColumn


Galileo Computing

12.6.4 Relationen zwischen Tabellen festlegen  toptop

In relationalen Datenbanken sind Tabellen über Schlüsselfelder miteinander verbunden. Die Tabelle Personal verfügt beispielsweise über die Spalte Personal-Nr mit einer eindeutigen Identifikationsnummer für den jeweiligen Datensatz. Die Tabelle Bestellungen aus der Nordwind-Datenbank enthält ebenfalls eine Spalte Personal-Nr. Auf diese Weise lässt sich festhalten, welcher Angestellte welche Bestellung bearbeitet hat. Typischerweise ergeben sich hier 1:n-Beziehungen. Zu einem Datensatz aus der Personal-Tabelle passen jeweils viele Datensätze aus der Bestellungen-Tabelle.


Achtung   Wenn Sie Tabellen aus einer Datenbank in ein DataSet-Objekt übertragen, werden solche Relationen nicht automatisch mit übertragen, sondern Sie müssen sie ausdrücklich festlegen.

So legen Sie eine Relation zwischen zwei Tabellen über die jeweiligen Schlüsselfelder fest:

1. Erstellen Sie ein DataColumn-Objekt von der Schlüssel-Spalte der Haupttabelle. Im Beispiel ist das das Feld Personal-Nr der Tabelle Personal. Dim parentCol As DataColumn
parentCol = _
myDS.Tables("Personal").Columns("Personal-Nr") 2. Erstellen Sie ein weiteres DataColumn-Objekt von derjenigen Spalte in der Kind-Tabelle, die den Schlüssel zur Master-Tabelle enthält. Das ist im Beispiel das Feld Personal-Nr aus der Tabelle Bestellungen. Dim childCol As DataColumn
childCol = _
myDS.Tables("Bestellungen").Columns("Personal-Nr") 3. Erstellen Sie ein neues DataRelation-Objekt auf der Grundlage dieser beiden DataRow-Objekte und geben Sie dabei der Relation einen Namen. Dim myRel As DataRelation
myRel = New DataRelation _
("bearbeitet von", parentCol, childCol) 4. Fügen Sie das neu erstellte DataRelation-Objekt an die DataRelationCollection des DataSet-Objekts an. myDS.Relations.Add (myRel)

Wenn Sie die Tabellendaten auswerten, ergeben sich im Bezug auf Relationen zwei typische Situationen:

gp  Ausgehend von der Zeile einer Haupttabelle möchten Sie auf die zugehörigen Einträge in einer Kindtabelle zugreifen.
gp  Oder genau andersherum: Von einem Eintrag in einer Kindtabelle möchten Sie auf die zugehörige Haupttabelle zugreifen.

So erreichen Sie die zugehörigen Einträge der Kind-Tabelle:

Die DataRow-Klasse bietet die Methode GetChildRows() an. Sie übergeben der Methode GetChildRows() den Namen der gewünschten Relation und erhalten die zugehörigen Einträge der Kind-Tabelle in Form eines Arrays von DataRow-Objekten.

Für den umgekehrten Weg bietet die DataRow-Klasse die Methoden GetParentRow() und GetParentRows() an. Auch hier übergeben Sie den Namen der Relation und erhalten ein einzelnes DataRow-Objekt oder ein Array aus DataRow-Objekten.

db_11.aspx fasst die vorgestellten Schritte in einem Skript zusammen. Abbildung 12.14 zeigt die Darstellung im Browser. Für jeden Angestellten, den die Personal-Tabelle verzeichnet, werden diejenigen Bestellungen aufgelistet, die er bearbeitet hat.

<!-- db_11.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 herstellen
   Dim conn As New OleDbConnection(connStr)
   conn.Open()   
   ' Kommando-Objekt vorbereiten
   Dim cmd As New OleDbCommand()
   cmd.Connection = conn
   ' Adapter-Objekt vorbereiten
   Dim myAdapter As New OleDbDataAdapter()
   myAdapter.SelectCommand = cmd
   ' DataSet-Objekt vorbereiten
   Dim myDS As New DataSet()
            
   ' Einige Spalten aus der Tabelle "Personal" einlesen
   Dim sql1 As String
   sql1 = "SELECT [Personal-Nr], Vorname, Nachname " 
   sql1 += "FROM Personal" 
   cmd.CommandText = sql1
   myAdapter.Fill (myDS, "Personal")

   ' Einige Spalten aus der Tabelle "Bestellungen" 
   ' einlesen
   Dim sql2 As String
   sql2 = "SELECT [Personal-Nr], Bestelldatum, " & _
          "[Bestell-Nr], Empfänger FROM Bestellungen"
   cmd.CommandText = sql2
   myAdapter.Fill (myDS, "Bestellungen")
   
   ' Relation zwischen "Personal" und "Bestellungen" 
   ' definieren:
   ' Die beteiligten Spalten festlegen.
   Dim parentCol As DataColumn
   Dim childCol As DataColumn
   parentCol = _
         myDS.Tables("Personal").Columns("Personal-Nr")
   childCol = _ 
     myDS.Tables("Bestellungen").Columns("Personal-Nr")
   ' Die Relation erstellen ...
   Dim myRel As DataRelation
   myRel = New DataRelation _
                ("bearbeitet von", parentCol, childCol)
   ' ... und dem Dataset hinzufügen.
   myDS.Relations.Add (myRel)

   Dim sb As New StringBuilder
   sb.Append ("Wer hat welche Bestellungen ")
   sb.Append ("bearbeitet?<br><br>")   
   
   Dim persRow As DataRow
   Dim bestRow As DataRow
   Dim myDate as DateTime
   ' Den Namen des Angestellten ausgeben
   For Each persRow In myDS.Tables("Personal").Rows
      sb.Append ("<br><b>" & _
                 persRow("Vorname").toString() & _
                 " " & _
                 persRow("Nachname").toString() & _
                 "</b><ul>")      
      ' Die zugeordneten Bestellungen ausgeben
      sb.Append("Bestelldatum – Bestell-Nr – Kunde")
      For Each bestRow In persRow.getChildRows _
                                     ("bearbeitet von")
         sb.Append ("<li>")
         myDate = CDate(bestRow(1))
         sb.Append (myDate.toShortDateString)
         sb.Append (", ")
         sb.Append (bestRow(2).toString() & ", ")
         sb.Append (bestRow(3).toString() & ", ")
      Next
      sb.Append ("</ul>")      
   Next
   
   ausgabe.innerHTML = sb.toString()
   conn.Close()
End Sub
</script>
<html><head><title>
Relationen zwischen Tabellen verwenden</title></head>
<body>
<h3>Relationen zwischen Tabellen verwenden</h3>
<p id="ausgabe" runat="server" />
</body></html>

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

Abbildung 12.14 Mit Hilfe von DataRelation-Objekten stellen Sie Relationen zwischen Haupttabellen und Kindtabellen her.

  

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