Rheinwerk Computing < openbook > Rheinwerk Computing - Professionelle Bücher. Auch für Einsteiger.
Professionelle Bücher. Auch für Einsteiger.

Inhaltsverzeichnis
1 Einführung
2 Grundlagen der Sprachsyntax
3 Klassendesign
4 Weitere Datentypen
5 Multithreading
6 Collections und LINQ
7 Eingabe und Ausgabe
8 Anwendungen: Struktur und Installation
9 Code erstellen und debuggen
10 Einige Basisklassen
11 Windows-Anwendungen erstellen
12 Die wichtigsten Steuerelemente
13 Tastatur- und Mausereignisse
14 MDI-Anwendungen
15 Grafiken mit GDI+
16 Drucken
17 Entwickeln von Steuerelementen
18 Programmiertechniken
19 WPF – Grundlagen
20 Layoutcontainer
21 WPF-Steuerelemente
22 Konzepte von WPF
23 Datenbankverbindung mit ADO.NET
24 Datenbankabfragen mit ADO.NET
25 DataAdapter
26 Offline mit DataSet
27 Datenbanken aktualisieren
28 Stark typisierte DataSets
A Anhang: Einige Übersichten
Stichwort

Jetzt Buch bestellen
Ihre Meinung?

Spacer
<< zurück
Visual Basic 2008 von Andreas Kuehnel, Stephan Leibbrandt
Das umfassende Handbuch
Buch: Visual Basic 2008

Visual Basic 2008
3., aktualisierte und erweiterte Auflage, geb., mit DVD
1.323 S., 49,90 Euro
Rheinwerk Computing
ISBN 978-3-8362-1171-0
Pfeil 28 Stark typisierte DataSets
Pfeil 28.1 Erzeugung
Pfeil 28.1.1 Visual Studio Designer
Pfeil 28.1.2 Das Kommandozeilentool XSD.exe
Pfeil 28.2 Anatomie
Pfeil 28.2.1 Grobstruktur: Datentypen
Pfeil 28.2.2 Das typisierte DataSet
Pfeil 28.2.3 TableAdapter
Pfeil 28.2.4 Typisierte Tabelle
Pfeil 28.2.5 Typisierte Zeile
Pfeil 28.3 Datenzugriff
Pfeil 28.3.1 Datenzeilen ausgeben
Pfeil 28.3.2 Datenzeilen hinzufügen
Pfeil 28.3.3 Datenzeilen bearbeiten
Pfeil 28.3.4 Datenzeilen suchen
Pfeil 28.3.5 Spalten mit Null-Wert
Pfeil 28.3.6 Tabellenbeziehungen
Pfeil 28.4 Ein typisiertes DataSet manuell erzeugen
Pfeil 28.4.1 DataTable erzeugen
Pfeil 28.4.2 Spalten hinzufügen
Pfeil 28.4.3 Tabellenbeziehungen erstellen
Pfeil 28.5 TableAdapter erzeugen
Pfeil 28.5.1 Visual Studio Assistent
Pfeil 28.6 TableAdapter verwenden
Pfeil 28.6.1 Datenbeschaffung mit Fill
Pfeil 28.6.2 Datenbeschaffung mit GetData
Pfeil 28.6.3 Aktualisierung mit Update
Pfeil 28.6.4 Aktualisieren mit UpdateAll
Pfeil 28.6.5 Direkte Aktualisierung der Datenbank
Pfeil 28.6.6 TableAdapter mit mehreren Abfragen
Pfeil 28.6.7 TableAdapter ändern
Pfeil 28.7 Fazit: Typisierte oder nicht typisierte DataSets?


Rheinwerk Computing - Zum Seitenanfang

28.2 Anatomie Zur nächsten ÜberschriftZur vorigen Überschrift

Die vom Designer von Visual Studio erzeugte Datei NWDataSet.Designer.vb ist mit über 2000 Zeilen recht lang. In diesem Kapitel werde ich Sie durch wesentliche Teile führen.


Rheinwerk Computing - Zum Seitenanfang

28.2.1 Grobstruktur: Datentypen Zur nächsten ÜberschriftZur vorigen Überschrift

Das stark typisierte DataSet ist von DataSet abgeleitet und enthält als innere Klassen einige öffentliche Datentypen, die die Tabellen, Zeilen und Zeilenänderungsereignisse repräsentieren. Damit ist die Datenbankstruktur beschrieben. Zusätzlich wird für jede Tabelle ein Table-Adapter erzeugt, der Methoden zum Beziehen und Ändern der Daten enthält. Schließlich ist der TableAdapterManager zum Abgleich der Daten mit der Datenbank gedacht, da er die referenzielle Integrität der Daten durch Steuerung der Aktualisierungsreihenfolge sicherstellt.

Class NWDataSet : Inherits DataSet

 
' Klassenmitglieder des nächsten Abschnitts
 
...

 
Class ProductsDataTable : Inherits TypedTableBase(Of ProductsRow)
 
Class CategoriesDataTable : Inherits TypedTableBase(Of CategoriesRow)

 
Class ProductsRow : Inherits DataRow
 
Class CategoriesRow : Inherits DataRow

 
Class ProductsRowChangeEvent : Inherits EventArgs
 
Class CategoriesRowChangeEvent : Inherits EventArgs
End Class

Namespace NWDataSetTableAdapters

 
Class ProductsTableAdapter : Inherits Component

 
Class CategoriesTableAdapter : Inherits Component

 
Class TableAdapterManager : Inherits Component

End Namespace

Hinweis
Eine Basisklasse »TableAdapter« gibt es nicht.



Hinweis
Jede innere Klasse muss beim Gebrauch mit NWDataSet qualifiziert werden.



Rheinwerk Computing - Zum Seitenanfang

28.2.2 Das typisierte DataSet Zur nächsten ÜberschriftZur vorigen Überschrift

Das typisierte DataSet selbst enthält alle Funktionalität, um auf die Daten der Abfrage zuzugreifen. Da die gesamte Struktur bei der automatischen Erstellung des Datentyps aus der Datenbankabfrage ermittelt wurde, reicht ein parameterloser Konstruktor. Am wichtigsten sind die beiden streng typisierten Tabellen. Die beiden Delegates wären meiner Meinung nach besser in den zugehörigen Tabellen aufgehoben.

Class NWDataSet : Inherits DataSet

 
Sub New()
 
Function Clone() As DataSet

 
ReadOnly Property Products() As ProductsDataTable
 
ReadOnly Property Categories() As CategoriesDataTable
 
ReadOnly Property Tables() As DataTableCollection
 
ReadOnly Property Relations() As DataRelationCollection

 
Property SchemaSerializationMode() As SchemaSerializationMode
 
Shared Function GetTypedDataSetSchema(xs As XmlSchemaSet) _
     
As XmlSchemaComplexType

 
Delegate Sub ProductsRowChangeEventHandler _
     
(sender As Object, e As ProductsRowChangeEvent)
 
Delegate Sub CategoriesRowChangeEventHandler _
     
(sender As Object, e As CategoriesRowChangeEvent)

 
' Datentypen des vorigen Abschnitts
 
...

End Class

Als erstes Beispiel soll ein typisiertes DataSet erzeugt werden. Durch die kleine Anweisung New NWDataSet() werden alle Eigenschaften und damit alle beteiligten Tabellen initialisiert (aber nicht mit Daten befüllt). Folglich sind dann bereits die gesamte Struktur der Tabellen und die Beziehungen untereinander bekannt. Das folgende Codefragment zeigt den Zugriff auf Spaltennamen und Fremdschlüsselbeziehungen (dessen Bedeutung ist an dieser Stelle unwichtig).


'...\ADO\DataSetTypisiert\TypisiertesDataSet.vb

Option Strict On 
Imports System.Data.Common, System.Data.SqlClient
Namespace ADO
 
Module TypisiertesDataSet
   
Sub Test()
     
Dim nw As New NWDataSet()

      Console
.Write("Spalten: ")
     
For Each col As DataColumn In nw.Products.Columns
        Console
.Write("{0} ", col.Caption)
     
Next

     
For Each rel As DataRelation In nw.Relations
        Console
.Write(Environment.NewLine & "{0}: ", rel.RelationName)
       
For no As Integer = 0 To rel.ChildColumns.Length 1
          Console
.Write("{0}.{1} -> {2}.{3}", _
            rel
.ParentColumns(no).Table.TableName, _
            rel
.ParentColumns(no).Caption, _
            rel
.ChildColumns(no).Table.TableName, _
            rel
.ChildColumns(no).Caption)
       
Next
     
Next rel

      Console
.ReadLine()
   
End Sub
 
End Module
End Namespace

Hinweis
Die Struktur eines typisierten DataSets ist ohne (erneuten) Kontakt zur Datenbank bekannt.



Rheinwerk Computing - Zum Seitenanfang

28.2.3 TableAdapter Zur nächsten ÜberschriftZur vorigen Überschrift

Im typisierten DatSet übernimmt der TableAdapter die Rolle des DataAdapters im untypisierten Fall. Er hat daher eine Fill-Methode, um die Tabelle mit Werten aus der Datenbank zu füllen, sowie Update-, Insert- und Delete-Methoden zur Änderung der Daten. Verbindungsdaten und Abfragekommandos werden bei der Erzeugung des TableAdapters direkt in den Quelltext geschrieben und in privaten Initialisierungsroutinen an einen SqlDataAdapter weitergereicht, der sich intern um die Kommunikation mit der Datenbank kümmert. Entsprechende öffentliche Methoden und Eigenschaften fehlen daher. Als Beispiel zeigt das nächste Codefragment den TableAdapter der Categories-Tabelle.

Class CategoriesTableAdapter : Inherits Component

 
Sub New()
 
Property ClearBeforeFill() As Boolean
 
Function Fill(dataTable As NWDataSet.CategoriesDataTable) As Integer
 
Function GetData() As NWDataSet.CategoriesDataTable

 
Function Update(dataTable As NWDataSet.CategoriesDataTable) As Integer
 
Function Update(dataSet As NWDataSet) As Integer
 
Function Update(dataRow As DataRow) As Integer
 
Function Update(dataRows() As DataRow) As Integer
 
Function Update(CategoryName As String, Original_CategoryID As Integer, _
    Original_CategoryName
As String, CategoryID As Integer) As Integer
 
Function Update(CategoryName As String, Original_CategoryID As Integer, _
    Original_CategoryName
As String) As Integer

 
Function Insert(CategoryName As String) As Integer
 
Function Delete(Original_CategoryID As Integer, _
        Original_CategoryName
As String) As Integer

End Class

Alle Methodenparameter, die Tabellen beschreiben, müssen sich auf die Categories-Tabelle beziehen. Da diese als innere Klasse CategoriesDataTable von NWDataSet definiert ist (siehe Abschnitt 28.2.1, »Grobstruktur: Datentypen«), muss sie mit NWDataSet. qualifiziert werden. Zur Verdeutlichung sind Categories und NWDataSet kursiv gesetzt.


Hinweis
Der in Visual Studio 2008 eingeführte TableAdapterManager ist für den Abgleich mit der Datenbank noch besser geeignet, da er auch während des Abgleichs die referenzielle Integrität der Datenbank sicherstellt.


Als einfaches Beispiel zeigt das nächste Codefragment, wie die Products-Tabelle mit Werten aus der Datenbank befüllt wird. Dazu verwenden Sie den typisierten Adapter ProductsTableAdapter. Er ist im Namensraum NWDataSetTableAdapters definiert. Der Fill-Methode des Adapters übergeben Sie die typrichtige Products–Tabelle aus dem typisierten DataSet namens NWDataSet. Dies ist ganz analog zum DataAdapter (siehe Kapitel 25, »Data-Adapter«). Um das Beispiel einfach zu halten, wird hier nicht mit den Daten gearbeitet.


'...\ADO\DataSetTypisiert\TableAdapter.vb

Option Strict On 
Imports System.Data.Common, System.Data.SqlClient
Namespace ADO
 
Module TableAdapter
   
Sub Test()
     
Dim nw As New NWDataSet()
     
Dim nwa As New NWDataSetTableAdapters.ProductsTableAdapter()
     
Dim zeilen As Integer = nwa.Fill(nw.Products)
      Console
.WriteLine("{0} Zeilen der Tabelle {1} gelesen", _
                        zeilen
, nwa.GetData().TableName)
      Console
.ReadLine()
   
End Sub
 
End Module
End Namespace

Die Ausgabe bestätigt den korrekten Zugriff:

77 Zeilen der Tabelle Products gelesen

Hinweis
Ein explizites Connection- oder Command-Objekt ist beim typisierten TableAdapter überflüssig. Andererseits kann er nur mit der typrichtigen Tabelle verwendet werden.



Rheinwerk Computing - Zum Seitenanfang

28.2.4 Typisierte Tabelle Zur nächsten ÜberschriftZur vorigen Überschrift

Jede Tabelle in einem typisierten DataSet wird durch eine eigene Eigenschaft mit eigenem Datentyp repräsentiert. Dieser enthält für jede Spalte eine eigene Eigenschaft und eine Standardeigenschaft, um die Spalten über ihre Position anzusprechen. Außerdem wird der typkorrekte Zugriff auf Zeilen geregelt: das Hinzufügen und Löschen von Zeilen, inklusive eigener Ereignistypen, sowie das Suchen nach Primärschlüsseln. Als Beispiel zeigt das nächste Codefragment den Datentyp für die Categories-Tabelle.

Class CategoriesDataTable : Inherits TypedTableBase(Of CategoriesRow)

 
Sub New()
 
Function Clone() As DataTable

 
ReadOnly Property CategoryIDColumn()   As DataColumn
 
ReadOnly Property CategoryNameColumn() As DataColumn
 
ReadOnly Property Count() As Integer
 
Default ReadOnly Property Item(index As Integer) As CategoriesRow

 
Event CategoriesRowChanging As CategoriesRowChangeEventHandler
 
Event CategoriesRowChanged  As CategoriesRowChangeEventHandler
 
Event CategoriesRowDeleting As CategoriesRowChangeEventHandler
 
Event CategoriesRowDeleted  As CategoriesRowChangeEventHandler

 
Function NewCategoriesRow() As CategoriesRow
 
Sub      AddCategoriesRow(row As CategoriesRow)
 
Function AddCategoriesRow(CategoryName As String) As CategoriesRow
 
Function FindByCategoryID(CategoryID As Integer) As CategoriesRow
 
Sub      RemoveCategoriesRow(row As CategoriesRow)

 
Shared Function GetTypedTableSchema(xs As XmlSchemaSet) As XmlSchemaComplexType
End Class

Rheinwerk Computing - Zum Seitenanfang

28.2.5 Typisierte Zeile topZur vorigen Überschrift

Jeder Spalte eines typisierten DataSets wird eine Eigenschaft zugeordnet. Einerseits werden dadurch die Spalten ohne Anführungszeichen angegeben und von IntelliSense gefunden. Andererseits erzwingt die strenge Typisierung das korrekte Datenformat. Für jede Spalte, die Nullwerte erlaubt, sind außerdem noch Methoden zum Testen und Setzen eines Nullwerts vorhanden. Das nächste Codefragment zeigt als Beispiel den Zeilentyp der Products-Tabelle.

Class ProductsRow : Inherits DataRow 
 
Property ProductID()   As Integer
 
Property ProductName() As String
 
Property CategoryID()  As Integer
 
Property UnitPrice()   As Decimal

 
Property CategoriesRow() As CategoriesRow

 
Function IsCategoryIDNull() As Boolean
 
Sub SetCategoryIDNull()
 
Function IsUnitPriceNull() As Boolean
 
Sub SetUnitPriceNull()
End Class

Hinweis
Da die Spaltenwerte nicht vom Typ Nullable sind, müssen Sie leider etwas Code hinzufügen, wenn Sie die Werte direkt an ein Control binden, um Nullwerte zu vermeiden. Außerdem sind die Zuweisungen spalte=Nothing und spalte=DBNull.Value verboten.


Der Gebrauch ist sehr einfach. Statt des Spaltennamens wird die gleichnamige Eigenschaft verwendet. Das hat in der Praxis den unschätzbaren Vorteil, dass der Compiler Tippfehler erkennt, die bei einer Indizierung mit Zeichenketten erst zur Laufzeit auffallen.

zeile.ProductName = "Irgendwas" 
Console
.WriteLine("Produkt {0}", zeile.ProductName)


Ihre Meinung

Wie hat Ihnen das Openbook gefallen? Wir freuen uns immer über Ihre Rückmeldung. Schreiben Sie uns gerne Ihr Feedback als E-Mail an kommunikation@rheinwerk-verlag.de.

<< zurück
  Zum Rheinwerk-Shop
Zum Rheinwerk-Shop: Visual Basic 2008
Visual Basic 2008
Jetzt Buch bestellen


 Ihre Meinung?
Wie hat Ihnen das Openbook gefallen?
Ihre Meinung

 Buchempfehlungen
Zum Rheinwerk-Shop: Visual Basic 2012






 Visual Basic 2012


Zum Rheinwerk-Shop: Schrödinger programmiert C++






 Schrödinger
 programmiert C++


Zum Rheinwerk-Shop: IT-Handbuch für Fachinformatiker






 IT-Handbuch für
 Fachinformatiker


Zum Rheinwerk-Shop: Professionell entwickeln mit Visual C# 2012






 Professionell
 entwickeln mit
 Visual C# 2012


Zum Rheinwerk-Shop: Windows Presentation Foundation






 Windows Presentation
 Foundation


 Lieferung
Versandkostenfrei bestellen in Deutschland, Österreich und der Schweiz
InfoInfo




Copyright © Rheinwerk Verlag GmbH 2009
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.


Nutzungsbestimmungen | Datenschutz | Impressum

Rheinwerk Verlag GmbH, Rheinwerkallee 4, 53227 Bonn, Tel.: 0228.42150.0, Fax 0228.42150.77, service@rheinwerk-verlag.de

Cookie-Einstellungen ändern