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