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 26 Offline mit DataSet
Pfeil 26.1 Das DataSet-Objekt verwenden
Pfeil 26.1.1 Ein DataSet-Objekt erzeugen
Pfeil 26.1.2 Anatomie einer DataTable
Pfeil 26.1.3 Zugriff auf eine Tabelle im DataSet
Pfeil 26.1.4 Zugriff auf die Ergebnisliste
Pfeil 26.1.5 Dateninformationen in eine XML-Datei schreiben
Pfeil 26.2 DataSet mit Schemainformationen
Pfeil 26.2.1 Schemainformationen bereitstellen
Pfeil 26.2.2 Gültigkeitsprüfung in einer DataColumn
Pfeil 26.2.3 Constraints-Klassen einer DataTable
Pfeil 26.2.4 Tabellenschema durch Programmcode
Pfeil 26.2.5 Tabellenschema durch DataAdapter
Pfeil 26.2.6 Tabellenschema aus einer XML-Datei
Pfeil 26.3 Änderung einer Tabelle
Pfeil 26.3.1 Editieren einer Datenzeile
Pfeil 26.3.2 Löschen einer Datenzeile
Pfeil 26.3.3 Neue Datenzeile hinzufügen
Pfeil 26.4 Änderung einer Datenzeile
Pfeil 26.4.1 Aktualisierungszustand
Pfeil 26.4.2 Ursprünglicher und aktualisierter Inhalt
Pfeil 26.4.3 Zeilenstatus manuell steuern
Pfeil 26.5 Mit mehreren Tabellen arbeiten
Pfeil 26.5.1 JOIN-Abfragen
Pfeil 26.5.2 Mehrere Tabellen in einem DataSet
Pfeil 26.5.3 Tabellenbeziehungen erzeugen
Pfeil 26.5.4 DataRelations und Einschränkungen
Pfeil 26.5.5 In Beziehung stehende Daten suchen
Pfeil 26.5.6 Ergänzung zum Speichern von Schemainformationen in einer XML–Schemadatei
Pfeil 26.6 Suchen und Filtern
Pfeil 26.6.1 Find
Pfeil 26.6.2 Select
Pfeil 26.7 Objekte vom Typ DataView
Pfeil 26.7.1 Initialisierung
Pfeil 26.7.2 Zugriff auf die Datenzeilen
Pfeil 26.7.3 Spalten durchsuchen
Pfeil 26.7.4 Mehrdeutige Suchergebnisse
Pfeil 26.7.5 Datenfilter
Pfeil 26.7.6 Statusfilter
Pfeil 26.7.7 Änderungen
Pfeil 26.7.8 DataView in DataTable umwandeln


Rheinwerk Computing - Zum Seitenanfang

26.5 Mit mehreren Tabellen arbeiten Zur nächsten ÜberschriftZur vorigen Überschrift


Rheinwerk Computing - Zum Seitenanfang

26.5.1 JOIN-Abfragen Zur nächsten ÜberschriftZur vorigen Überschrift

Bisher haben wir immer nur eine Tabelle im DataSet betrachtet. In der Praxis sind oft mehrere Tabellen gleichzeitig im Spiel. Um beispielsweise die Frage zu beantworten, welche Artikel von den einzelnen Lieferanten stammen, sind zwei Tabellen notwendig: Products und Suppliers. Die meisten Tabellen einer Datenbank stehen mit anderen Tabellen in Beziehung. Meistens handelt es sich dabei um 1:n-Beziehungen. Beispielsweise stammen von einem Lieferanten mehrere Artikel. Allerdings berücksichtigt die Northwind-Datenbank nicht, dass ein bestimmtes Produkt durchaus auch von mehreren Lieferanten angeboten werden könnte. Dann müsste die Beziehung zwischen den beiden Tabellen durch eine m:n-Beziehung beschrieben werden, die normalerweise in drei Tabellen aufgelöst wird, die miteinander jeweils in einer 1:n-Beziehung stehen. Diese Aufteilung ergibt sich aus der angestrebten Normalisierung der Datentabellen, die eine »robuste« Datenbank ergeben. Das Prinzip der Normalisierung wurde von Boyce und Codd in den 1970er-Jahren eingeführt.

Wenden wir uns für die weiteren Ausführungen nun zwei Tabellen zu, deren Beziehung Sie in Abbildung 26.2 sehen.

Um Daten aus mehreren Tabellen auszuwerten, werden JOIN-Abfragen benutzt, zum Beispiel um festzustellen, welche Produkte von den einzelnen Lieferanten angeboten werden:

SELECT Suppliers.CompanyName, Suppliers.ContactName, 
       Products.ProductName 
FROM Suppliers INNER JOIN Products 
     ON Suppliers.SupplierID = Products.SupplierID

Das Ergebnis der Abfrage kombiniert Daten aus beiden Tabellen:

             Exotic Liquids  Charlotte Cooper                          Chai 
             Exotic Liquids  Charlotte Cooper                         Chang 
             Exotic Liquids  Charlotte Cooper                 Aniseed Syrup 
 New Orleans Cajun Delights     Shelley Burke  Chef Anton's Cajun Seasoning 
 New Orleans Cajun Delights     Shelley Burke        Chef Anton's Gumbo Mix 
   ...

Abbildung 26.2 Beziehung zwischen »Products« und »Suppliers«

JOIN-Abfragen haben einige Vorteile:

  • Das Ergebnis lässt sich filtern.
  • Das Resultat steht in einer überschaubaren Ergebnismenge.
  • JOIN-Abfragen sind anerkannter Standard.

Bei kritischer Betrachtung stehen den Vorteilen aber auch gewichtige Nachteile gegenüber:

  • Die Daten einer JOIN-Abfrage sind schwierig zu aktualisieren. Insbesondere beim Löschen oder Hinzufügen einer Datenzeile in einer Join-Abfrage wird die Problematik deutlich. Angenommen, Sie löschen eine Datenzeile, steht sofort die Frage im Raum, ob nur die Datenzeile in der Detailtabelle, also auf der n-Seite einer Beziehung gelöscht werden soll oder gleichzeitig auch die Datenzeile in der übergeordneten Mastertabelle, also der 1-Seite.
  • JOIN-Abfragen geben redundante Daten zurück. Lassen Sie sich beispielsweise die Artikelliste ausgeben und zu jedem Artikel auch noch die notwendigen Informationen des entsprechenden Lieferanten, werden die Lieferanteninformationen mehrfach zurückgeliefert (siehe das letzte Abfrageergebnis).
  • Änderungen in einer JOIN-Abfrage sind schwer zu synchronisieren. Firmiert sich einer der Lieferanten um und tragen Sie das im Abfrageergebnis ein, muss die Änderung sofort zur Datenbank übermittelt und die gesamte Abfrage erneut ausgeführt werden.

Rheinwerk Computing - Zum Seitenanfang

26.5.2 Mehrere Tabellen in einem DataSet Zur nächsten ÜberschriftZur vorigen Überschrift

ADO.NET löst die Nachteile, die eine JOIN-Abfrage hat, auf eigene Art und Weise. Dazu wird die JOIN-Abfrage in Einzeltabellen aufgeteilt, die miteinander in Beziehung gesetzt werden. Mit anderen Worten: Es wird ein Teil der Originaldatenbank abgebildet. Die Beziehung zwischen zwei Tabellen wird durch ein Objekt vom Typ DataRelation beschrieben.

Solche strukturierten DataSets sind schwer zu filtern, aber sie haben entscheidende Vorteile. So werden weniger Daten zurückgegeben als bei einer JOIN-Abfrage. Damit wird einerseits sowohl die Netzbelastung als auch die Auslastung des lokalen Speichers so gering wie möglich gehalten. Zudem ist es viel einfacher, Daten zu aktualisieren. Löschen Sie zum Beispiel einen Datensatz aus der Detailtabelle (n-Seite), möchten Sie vermutlich nicht auch gleichzeitig den entsprechenden Datensatz der Mastertabelle löschen (1-Seite). Beide Informationen sind in einer JOIN-Abfrage jedoch in einer Datenzeile zusammengefasst. Operieren Sie mit einer DataRelation zwischen zwei DataTable-Objekten, lässt sich der Datensatz aus der Detailtabelle löschen, ohne dass zwangsläufig auch die entsprechende Datenzeile der Mastertabelle gelöscht wird.


Rheinwerk Computing - Zum Seitenanfang

26.5.3 Tabellenbeziehungen erzeugen Zur nächsten ÜberschriftZur vorigen Überschrift

Die Verknüpfung von zwei DataTable-Objekten in einer DataRelation erfolgt über DataColumn-Objekte. In der Products/Suppliers-Beziehung ist die Tabelle Suppliers das übergeordnete Element und die Tabelle Products das untergeordnete Element der Beziehung. Dies ist vergleichbar mit einer Primärschlüssel/Fremdschlüssel-Beziehung. Beziehungen werden zwischen einander entsprechenden Spalten in der übergeordneten und der untergeordneten Tabelle erstellt. Das heißt, dass der Datentyp für beide Spalten identisch sein muss.

Ich möchte Ihnen im Folgenden den ersten der DataRelation-Konstruktoren vorstellen (optionale Teile sind in eckige Klammern gesetzt, [()] bedeutet einfaches Objekt oder Feld).


Sub New(relationName As String, _ 
  parentColumns As DataColumn[()], childColumns As DataColumn[()] 
  [,createConstraints As Boolean]) 
Sub New(relationName As String, _ 
  parentTableName As String [, parentTableNamespace As String], _ 
  childTableName As String [, childTableNamespace As String], _ 
  parentColumnNames As String(), childColumnNames As String(),nested As Boolean)

Der erste Parameter ist der Name, unter dem die DataRelation angesprochen wird, der zweite erwartet die Referenz auf die übergeordnete Spalte der Mastertabelle (1-Seite) und der dritte die Referenz auf die untergeordnete Spalte der Detailtabelle (n-Seite).

Nachdem eine DataRelation erzeugt worden ist, muss sie der Relations-Auflistung eines DataSets hinzugefügt werden. Die Auflistung hat den Typ DataRelationCollection.

Das folgende Beispiel zeigt, wie die durch ein Programm erzeugte Beziehung zwischen den beiden Tabellen Suppliers und Products festgelegt wird (der vollständige Code folgt später).

Dim conn As DbConnection = New SqlConnection() 
conn.ConnectionString = "..." 
Dim cmd As DbCommand = New SqlCommand() 
cmd.Connection = conn 
cmd.CommandText = "SELECT * FROM Suppliers;SELECT * FROM Products" 
Dim ds As DataSet = New DataSet() 
Dim da As DbDataAdapter = New SqlDataAdapter() 
da.SelectCommand = cmd 
da.TableMappings.Add("Table", "Händler") 
da.TableMappings.Add("Table1", "Produkte") 
da.Fill(ds) 
' Beziehung zwischen den beiden Tabellen 
Dim master As DataColumn = ds.Tables("Händler").Columns("SupplierID") 
Dim detail As DataColumn = ds.Tables("Produkte").Columns("SupplierID") 
Dim rel As DataRelation = New DataRelation("HändlerProdukte",master,detail) 
ds.Relations.Add(rel)

Rheinwerk Computing - Zum Seitenanfang

26.5.4 DataRelations und Einschränkungen Zur nächsten ÜberschriftZur vorigen Überschrift

Wenn Sie eine DataRelation zwischen zwei Tabellen erzeugen, wie zuvor gezeigt, wird ein UniqueConstraint auf der Mastertabelle und ein ForeignKeyConstraint auf der Detailtabelle erstellt.

Sind vor dem Erstellen der DataRelation Einschränkungen definiert, die einer Unique- und einer Fremdschlüsseleinschränkung entsprechen, übernimmt die neue DataRelation die vorhandenen Einschränkungen und erzeugt implizit keine neuen.

Sie können das implizite Erzeugen der Einschränkungen mit dem vierten Konstruktorparameter von DataRelation durch Angabe von False unterdrücken, zum Beispiel:

Dim rel As DataRelation = _ 
  New DataRelation("HändlerProdukte", master, detail, False)

ForeignKeyConstraint im Detail

Das ForeignKeyConstraint-Objekt gehört zur ConstraintCollection der Detailtabelle, also der Tabelle auf der n-Seite einer 1:n-Beziehung. Es weist nicht nur eine Reihe von Eigenschaften auf, um die Beziehung zwischen den beiden Tabellen zu untersuchen, sondern legt auch fest, wie sich die beiden Tabellen verhalten, wenn in der übergeordneten Mastertabelle Daten geändert oder Datenzeilen gelöscht werden.

Das folgende Codefragment zeigt, wie Sie die Eigenschaften Table, RelatedTable, Columns und RelatedColumns auswerten können. Die Auswertung basiert auf der Beziehung, die weiter oben zwischen den beiden Tabellen Suppliers und Products codiert worden ist (der vollständige Code folgt später).

Dim cons As ConstraintCollection = ds.Tables("Produkte").Constraints 
For Each con As Constraint in cons 
  If TypeOf con Is ForeignKeyConstraint Then 
    Dim col As DataColumn 
    Console.Write("Untergeordnete Tabelle: ") 
      Console.WriteLine(CType(con, ForeignKeyConstraint).Table) 
    Console.Write("Untergeordnete Spalte(n): ") 
      For Each col In CType(con, ForeignKeyConstraint).Columns 
        Console.Write(col.ColumnName & " ") 
      Next 
      Console.WriteLine() 
    Console.Write("Übergeordnete Tabelle: ") 
      Console.WriteLine(CType(con, ForeignKeyConstraint).RelatedTable) 
    Console.Write("Übergeordnete Spalte(n): ") 
      For Each col In CType(con, ForeignKeyConstraint).RelatedColumns 
          Console.WriteLine(col.ColumnName & " ") 
      Next 
      Console.WriteLine() 
  End If 
Next

Die in Beziehung stehenden Spalten und die Tabelle auf der Masterseite liefern die Eigenschaften RelatedColumns und RelatedTable der Einschränkung, auf der untergeordneten Seite sind es Columns und Table. Die Spalten werden als DataColumn-Array gespeichert, weil mehrere Spalten ein gemeinsames Merkmal für die Beziehung zwischen zwei Tabellen darstellen können.

Wichtiger als die Auswertung der Eigenschaften einer Beziehung sind die Eigenschaften, über die das Verhalten der Relation festgelegt wird. Wie sollen sich zum Beispiel die verknüpften Datenzeilen in der untergeordneten Detailtabelle verhalten, wenn Sie eine Datenzeile in der Mastertabelle löschen? Sollen sie ebenfalls gelöscht werden, oder sollen sie in der Detailtabelle erhalten bleiben? Wird der Wert in der untergeordneten Tabelle ebenfalls aktualisiert, wenn in der Mastertabelle ein Wert geändert wird?

Die Steuerung dieses Verhaltens wird von den Eigenschaften UpdateRule und DeleteRule bestimmt. Beide Eigenschaften sind vom Typ der Enumeration Rule im Namensraum System.Data, deren Werte in Tabelle 26.7 angegeben sind.


Tabelle 26.7 Konstanten der Enumeration »Rule«

Konstante Beschreibung

Cascade

Jede Löschung (Änderung) in der Mastertabelle wird auch in der Detailtabelle analog durchgeführt. Dies ist die Standardeinstellung.

None

Statt einer Aktion wird eine Ausnahme ausgelöst.

SetDefault

Die Werte in den verknüpften Datenzeilen der Detailtabelle werden auf die Standardwerte eingestellt, die in der Eigenschaft DefaultValue des DataColumn-Objekts festgelegt sind.

SetNull

Die Werte in den verknüpften Datenzeilen werden auf DBNull gesetzt.


Wichtig ist auch die Eigenschaft AcceptRejectRule, die steuert, wie mit den verknüpften Datenzeilen umgegangen wird, wenn in der Mastertabelle AcceptChanges oder RejectChanges aufgerufen wird.

Sie kann nur die Werte AcceptRejectRule.None oder AcceptRejectRule.Cascade annehmen. Der Standardwert None bewirkt, dass sich der Aufruf von AcceptChanges oder RejectChanges für eine Masterzeile nicht auf die Datenzeilen der untergeordneten Datenzeilen auswirkt. Wenn Sie die Eigenschaft AcceptRejectRule auf Cascade setzen, wird die Aktion an die untergeordnete Datenzeile weitergegeben, die im ForeignKeyConstraint-Objekt definiert ist.

Das folgende Beispielprogramm Relationen enthält zusammenfassend einige der Features, die im Zusammenhang mit der DataRelation stehen.


'...\ADO\DataSet\Relationen.vb

Option Strict On 
Imports System.Data.Common, System.Data.SqlClient 
Namespace ADO 
  Module Relationen 
    Sub Test() 
      Dim conn As DbConnection = New SqlConnection() 
      conn.ConnectionString = "Data Source=(local);" & _ 
          "Initial Catalog=Northwind;Integrated Security=sspi" 
      Dim cmd As DbCommand = New SqlCommand() 
      cmd.CommandText = "SELECT * FROM Suppliers;SELECT * FROM Products" 
      cmd.Connection = conn

      Dim ds As New DataSet() 
      Dim da As DbDataAdapter = New SqlDataAdapter() 
      da.SelectCommand = cmd 
      da.TableMappings.Add("Table", "Händler") 
      da.TableMappings.Add("Table1", "Produkte") 
      da.Fill(ds)

      ' Beziehung zwischen den beiden Tabellen 
      Dim master As DataColumn = ds.Tables("Händler").Columns("SupplierID") 
      Dim detail As DataColumn = ds.Tables("Produkte").Columns("SupplierID") 
      Dim rel As DataRelation = _ 
        New DataRelation("HändlerProdukte", master, detail) 
      ds.Relations.Add(rel)

      For Each con As Constraint In ds.Tables("Produkte").Constraints 
        If TypeOf con Is ForeignKeyConstraint Then 
          Dim col As DataColumn 
          Console.Write("Untergeordnete Tabelle: ") 
            Console.WriteLine(CType(con, ForeignKeyConstraint).Table) 
          Console.Write("Untergeordnete Spalte(n): ") 
            For Each col In CType(con, ForeignKeyConstraint).Columns 
              Console.Write(col.ColumnName & " ") 
            Next 
            Console.WriteLine() 
          Console.Write("Übergeordnete Tabelle: ") 
            Console.WriteLine(CType(con, ForeignKeyConstraint).RelatedTable) 
          Console.Write("Übergeordnete Spalte(n): ") 
            For Each col In CType(con, ForeignKeyConstraint).RelatedColumns 
              Console.WriteLine(col.ColumnName & " ") 
            Next 
            Console.WriteLine() 
        End If 
      Next

      ' Löschen einiger Händler 
      Print("Vor dem Löschen", ds) 
      Dim fkey As ForeignKeyConstraint = _ 
        CType(ds.Tables("Produkte").Constraints(0), ForeignKeyConstraint) 
      fkey.DeleteRule = Rule.SetNull 
      For i As Integer = 0 To 2 
        ds.Tables("Händler").Rows(i).Delete() 
      Next 
      Print("Nach Änderung", ds)

      Console.ReadLine() 
    End Sub

    Sub Print(ByVal header As String, ByVal ds As DataSet) 
      Console.WriteLine(header & ": ") 
      For Each row As DataRow In ds.Tables(0).Rows 
        If row.RowState <> DataRowState.Deleted Then _ 
          Console.WriteLine("{0,3}{1,35}", row(0), row(1)) 
      Next 
    End Sub 
  End Module 
End Namespace

Rheinwerk Computing - Zum Seitenanfang

26.5.5 In Beziehung stehende Daten suchen Zur nächsten ÜberschriftZur vorigen Überschrift

DataRelation-Objekte werden oft dazu benutzt, um Daten zu suchen, die in verschiedenen DataTable-Objekten enthalten sind. Zu diesem Zweck stellt eine DataRow drei Methoden zur Verfügung, die auf einer DataRelation basieren:

  • GetChildRows
  • GetParentRow
  • GetParentRows

GetChildRows sucht, ausgehend von einer Datenzeile in der Mastertabelle, alle zugehörigen untergeordneten Datenzeilen in der Detailtabelle. Dazu übergeben Sie der Methode die DataRelation, die die Tabellen verknüpft, und erhalten als Ergebnis ein DataRow-Array. In den folgenden Deklarationen sind optionale Teile in eckige Klammern gesetzt:


GetChildRows(relName As String [, ver As DataRowVersion]) As DataRow() 
GetChildRows(rel As DataRelation [, ver As DataRowVersion]) As DataRow()

Ausgehend von der untergeordneten Zeile einer Detailtabelle liefert GetParentRow die zugehörige übergeordnete Datenzeile aus der Mastertabelle. Auch hier müssen Sie die DataRelation zwischen den beiden Tabellen angeben; der Rückgabewert ist eine einzige Datenzeile.


GetParentRow(relName As String [, ver As DataRowVersion]) As DataRow() 
GetParentRow(rel As DataRelation [, ver As DataRowVersion]) As DataRow()

Sollte zwischen zwei Tabellen eine n:m-Beziehung bestehen, können Sie die GetParentRows-Methode einsetzen:


GetParentRows(relName As String [, ver As DataRowVersion]) As DataRow() 
GetParentRows(rel As DataRelation [, ver As DataRowVersion]) As DataRow()

Diese Methoden verwenden wir nun, um zu den einzelnen Aufträgen (Tabelle Orders) die bestellten Produkte (Tabelle Products) aufzulisten. Zwischen den beiden Tabellen besteht eine m:n-Beziehung, die durch die Tabelle Order Details in zwei 1:n-Beziehungen aufgelöst wird (siehe Abbildung 26.3).

Abbildung 26.3 Beziehungen der Tabellen »Orders«, »Order Details« und »Products«

In dem Beispiel werden die drei Tabellen mittels TableMappings umbenannt, um den Code lesbarer zu gestalten. Nachdem der DataAdapter die Daten abgerufen hat, werden in einer äußeren For Each-Schleife alle Datenzeilen der Tabelle Aufträge (Orders) nacheinander durchlaufen. Für jede Bestellnummer (OrderID) eines Auftrags (Datenzeile) werden mit GetChildRows über die Beziehung Auftragsdaten alle Bestellungen (OrderDetails) durchlaufen. Die Bestellung ermittelt mit GetParentRow über die Beziehung Produktdaten den korrespondierenden Auftrag in der Tabelle Aufträge (Orders) und daraus den Produktnamen.


'...\ADO\DataSet\Navigation.vb

Option Strict On 
Imports System.Data.Common, System.Data.SqlClient 
Namespace ADO 
  Module Navigation 
    Sub Test() 
      Dim conn As DbConnection = New SqlConnection() 
      conn.ConnectionString = "Data Source=(local);" & _ 
          "Initial Catalog=Northwind;Integrated Security=sspi" 
      Dim cmd As DbCommand = New SqlCommand() 
      cmd.CommandText = "SELECT * FROM Orders;" & _ 
        "SELECT * FROM [Order Details];SELECT * FROM Products" 
      cmd.Connection = conn

      Dim ds As New DataSet() 
      Dim da As DbDataAdapter = New SqlDataAdapter() 
      da.SelectCommand = cmd 
      da.TableMappings.Add("Table", "Aufträge") 
      da.TableMappings.Add("Table1", "Bestellung") 
      da.TableMappings.Add("Table2", "Produkte") 
      da.Fill(ds)

      ' Beziehung zwischen 'Orders' und 'Order Details' 
      Dim master As DataColumn = ds.Tables("Aufträge").Columns("OrderID") 
      Dim details As DataColumn = ds.Tables("Bestellung").Columns("OrderID") 
      Dim rel As DataRelation = _ 
        New DataRelation("Auftragsdaten", master, details) 
      ds.Relations.Add(rel)

      ' Beziehung zwischen 'Order Details' und 'Products' 
      master = ds.Tables("Produkte").Columns("ProductID") 
      details = ds.Tables("Bestellung").Columns("ProductID") 
      rel = New DataRelation("Produktdaten", master, details) 
      ds.Relations.Add(rel)

      ' Zu jeder Bestellung die bestellten Artikel anzeigen 
      For Each order As DataRow In ds.Tables("Aufträge").Rows 
        Console.WriteLine("BestellNummer: {0}", order("OrderID")) 
        For Each detail As DataRow _ 
          In order.GetChildRows(ds.Relations("Auftragsdaten")) 
          Dim product As DataRow = _ 
            detail.GetParentRow(ds.Relations("Produktdaten")) 
          Console.WriteLine("Artikel: {0}", product("ProductName")) 
        Next detail 
        Console.WriteLine(New String("-"c, 40)) 
      Next order

      Console.ReadLine() 
    End Sub 
  End Module 
End Namespace

Die Ausgabe zeigt, dass es mehrere Anbieter für denselben Artikel gibt:

BestellNummer: 10248 
Artikel: Queso Cabrales 
Artikel: Singaporean Hokkien Fried Mee 
Artikel: Mozzarella di Giovanni 
---------------------------------------- 
BestellNummer: 10249 
Artikel: Tofu 
Artikel: Manjimup Dried Apples 
---------------------------------------- 
...

Rheinwerk Computing - Zum Seitenanfang

26.5.6 Ergänzung zum Speichern von Schemainformationen in einer XML–Schemadatei topZur vorigen Überschrift

In Abschnitt 26.2.6, »Tabellenschema aus einer XML-Datei«, habe ich Ihnen gezeigt, wie Sie die Schemainformationen mit der Methode WriteXmlSchema des DataSets in einer XML-Schemadatei speichern können. Sie können selbstverständlich auf die gleiche Weise auch die Metadaten mehrerer Tabellen eines DataSets in einer Datei ablegen. Bitte beachten Sie aber, dass die Metadaten, die durch die Methode FillSchema in einem DataSet gespeichert wurden, nicht die Beziehungen zwischen den Tabellen berücksichtigen, auch wenn diese in der Originaldatenbank definiert sind.

Um auch die Beziehungen zwischen den Tabellen in der Schemadatei zu speichern, müssen Sie die Beziehungen zwischen den Tabellen zuerst mit Programmcode definieren, bevor Sie die Methode WriteXmlSchema aufrufen. So werden auch die von Ihnen definierten Tabellenbeziehungen in die XSD-Datei geschrieben.



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