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 27 Datenbanken aktualisieren
Pfeil 27.1 Aktualisieren mit CommandBuilder
Pfeil 27.1.1 Parallelitätskonflikt
Pfeil 27.1.2 Aktualisierungsbefehle des DbCommandBuilders
Pfeil 27.1.3 Aktualisierungsoptionen des DbCommandBuilders
Pfeil 27.1.4 Vor- und Nachteile des DbCommandBuilders
Pfeil 27.2 Manuell gesteuerte Aktualisierungen
Pfeil 27.2.1 Manuelles Aktualisieren mit dem DataAdapter
Pfeil 27.2.2 Aktualisieren mit ExecuteNonQuery
Pfeil 27.3 Benutzer über fehlgeschlagene Aktualisierungen informieren
Pfeil 27.4 Konfliktverursachende Datenzeilen bei der Datenbank abfragen
Pfeil 27.5 DataSet mit der Datenbank synchronisieren
Pfeil 27.5.1 UpdatedRowSource in DbCommand
Pfeil 27.6 Hierarchische Änderungen an die Datenbank übermitteln
Pfeil 27.6.1 Datenbank auslesen
Pfeil 27.6.2 Änderung
Pfeil 27.6.3 Bestellung einfügen
Pfeil 27.6.4 Bestelldetails einfügen
Pfeil 27.6.5 Wiederherstellen der Datenbank

Dieses Kapitel beschreibt den Abgleich der lokal gehaltenen Daten mit der Datenbank. Dabei werden insbesondere auch Konfliktsituationen berücksichtigt.

27 Datenbanken aktualisieren

Im letzten Kapitel haben wir uns ausgiebig mit den Daten im lokalen Speicher beschäftigt. Sie sind in Objekten von Typ DataTable enthalten und werden in einem DataSet verwaltet. Um die Synchronisation mit der Datenbank zu ermöglichen, werden die Daten sowohl im aktuellen Zustand als auch im Ursprungszustand (so, wie von der Originaldatenbank bezogen) gespeichert (Stichwort DataRowVersion). Ich habe Ihnen gezeigt, welche Möglichkeiten es gibt, die Daten im DataSet beliebig zu ändern. Nun folgt die »Krönung«: Wir schreiben geänderte Daten in die Originaldatenbank zurück.

Das Zurückschreiben in eine Datenbank ist nicht schwierig. Sie müssen nur ein entsprechendes SQL-UPDATE-Kommando an den Datenbankserver schicken, denn nur über SQL-Befehle können Sie mit einer Datenbank kommunizieren. Im einfachsten Fall genügt es, sich dazu an die Methode ExecuteNonQuery des Command-Objekts zu erinnern.

Solange Sie sicher davon ausgehen können, dass nur ein einziger Benutzer einen bestimmten Datensatz in der Datenbank ändern kann, ist das Thema »Aktualisierung« schnell erledigt: Sie schieben den geänderten Datensatz in die Originaldatenbank – fertig. Meistens aber haben wir es mit Mehrbenutzerumgebungen zu tun, in denen mehrere Anwender denselben Datensatz ändern dürfen. Denken Sie beispielsweise an die Online-Buchung einer Reise. Während mehrere potenzielle Reise-Interessenten noch den Familienrat tagen lassen und sich überlegen, ob sie das Superangebot eines Reiseveranstalters buchen sollen, bucht ein anderer Interessent schnell entschlossen die Reise. Versuchen später andere Interessenten, die Reise zu buchen, werden sie nach dem Absenden der Buchungsinformationen darauf aufmerksam gemacht, dass sie zu spät gekommen sind: Der Aktualisierungsversuch wird abgelehnt.

Solange wir mit verbindungsorientierten Datenbankzugriffen arbeiten, ist das Problem recht einfach zu lösen, da wir von den Sperrmechanismen der Datenbank unterstützt werden. Da ADO.NET jedoch eine verbindungslose Datenzugriffstechnologie ist, sind die Verhältnisse häufig nicht ganz so einfach und müssen gründlich analysiert werden.

Wann treten Konflikte auf?

Ehe ich auf die Aktualisierung einer Datenbank mit ADO.NET eingehe, möchte ich die Um-stände klären, unter denen in einer verbindungslosen Umgebung Konflikte auftreten können.

Ein Anwender A bezieht die Daten von einer Datenbank. Diese werden im lokalen Speicher abgelegt. und die Änderungen – Anwender A ändert den ursprünglichen Produktnamen Käse in Cheese – wirken sich zunächst nur im DataSet aus. Zu einem späteren Zeitpunkt entscheidet sich Anwender A, die Originaldatenbank mit der vorgenommenen Änderung zu synchronisieren, und schickt die geänderte Datenzeile zur Datenbank. Der SQL-Befehl könnte wie folgt aussehen (die WHERE-Klausel enthält den Produktnamen zur späteren Erläuterung der Problematik und ist technisch überflüssig, da ProductID eine Zeile bereits eindeutig identifiziert):

UPDATE Products 
SET ProductName = 'Cheese' 
WHERE ProductID = 55 AND ProductName = 'Käse'

Die Verbindung zur Datenbank wird geöffnet und der UPDATE-Befehl zur Datenbank geschickt, die ihrerseits die betroffene Zeile aktualisiert. Beachten Sie bitte die WHERE-Klausel, die bei einem UPDATE-Befehl dazu dient, in der Datenbank nach der zu aktualisierenden Datenzeile zu suchen. In allen Feldern der WHERE-Klausel werden die von der Datenbank bezogenen Originaldaten angegeben. Nur sie sind der Datenbank bekannt, da die Datenbank nichts von der lokalen Änderung weiß.

Aber es gibt vielleicht noch einen zweiten Anwender B, der dieselbe (ungeänderte) Datenzeile vom Datenbankserver bezogen hat und in seinem lokalen Speicher bearbeitet. Allerdings ändert Benutzer B nicht den Produktnamen, sondern den Einzelpreis. Selbstverständlich möchte auch Benutzer B seine Änderungen in die Datenbank schreiben. Nehmen wir an, er versucht es mit dem folgenden UPDATE-Befehl (mit derselben WHERE-Klausel wie A):

UPDATE Products 
SET UnitPrice = 12.98 
WHERE ProductID = 55 AND ProductName = 'Käse'

Anwender B hat dieselben Daten empfangen wie Anwender A und verwendet daher dieselbe WHERE-Klausel. Sie enthält den Wert Käse. Von der Änderung des Benutzers A weiß Benutzer B allerdings nichts. Abbildung 27.1 zeigt die Situation.

Abbildung 27.1 Konfliktsituation beim Aktualisieren

Der Aktualisierungsversuch von Benutzer B scheitert, denn die Datenzeile, die von der WHERE-Klausel des Benutzers B beschrieben wird, existiert nicht mehr – wegen der Änderung von Anwender A im Feld ProductName.

Anders sieht das Ergebnis für Anwender B aus, enthält die WHERE-Klausel von UPDATE als einziges Suchkriterium den Primärschlüssel der zu aktualisierenden Datenzeile:

UPDATE Products 
SET UnitPrice = 12.98 
WHERE ProductID = 55

Der Datensatz wird in der Datenbank gefunden, denn Anwender A hat ein Feld geändert, das in der WHERE-Klausel von Anwender B nicht angegeben ist.


Die Spaltenauswahl in der WHERE-Klausel bestimmt über den Erfolg einer Aktualisierung.


An dieser Stelle sollten wir uns überlegen, welche Situationen auftreten können, die zu einem Konflikt führen:

  • Ein Anwender B editiert eine Datenzeile, die ein Anwender A vorher aktualisiert hat. Je nach Formulierung der WHERE-Klausel wird die Aktualisierung durch Anwender B scheitern, weil die gesuchte Datenzeile in der Originaldatenbank nicht gefunden wird.
  • Anwender B versucht eine Datenzeile zu ändern, die Anwender A zuvor gelöscht hat.
  • Anwender B löscht eine Datenzeile, die schon gelöscht ist. Meistens wird man einen solchen Konflikt nicht behandeln müssen, er wird aber der Vollständigkeit halber erwähnt.
  • Anwender B fügt eine neue Datenzeile mit einem Primärschlüssel hinzu, der bereits existiert. Wenn die betreffende Tabelle den Primärschlüssel automatisch vergibt, kann diese Konfliktsituation natürlich nicht auftreten.

Tritt ein Konflikt auf, muss der Anwender mindestens über die Ursache der Ablehnung einer Aktualisierung informiert werden. Die Anwendung sollte dem Anwender weitergehende Informationen bereitstellen. Im Beispiel oben ist es sinnvoll, Anwender B mitzuteilen, dass Anwender A den Produktnamen verändert hat. Wenn beide Änderungen ihre Berechtigung haben, kann Anwender B dann einen erneuten Aktualisierungsversuch starten, der sowohl den neuen Produktnamen als auch den geänderten Einzelpreis berücksichtigt.

Konflikte können in jeder Umgebung auftreten, in der Änderungen verbindungslos vorgenommen werden, also auch unter ADO.NET. Daher gibt uns ADO.NET alles an die Hand, um aufgetretene Konflikte zu analysieren und zu lösen. Dieses Kapitel beschreibt, wie Sie dabei vorgehen. Dabei unterscheiden wir zwei Szenarien:

  • das automatische Aktualisieren unter Zuhilfenahme der Klasse CommandBuilder
  • das manuell gesteuerte Aktualisieren

Fangen wir zunächst mit der einfacheren, automatischen Aktualisierung an.


Rheinwerk Computing - Zum Seitenanfang

27.1 Aktualisieren mit CommandBuilder Zur nächsten ÜberschriftZur vorigen Überschrift

Sie können eine DataTable mit Daten aus jeder Datenquelle füllen. Handelt es sich um eine Datenbank und können die Benutzer die Daten auch ändern, müssen die Änderungen irgendwann an die Datenbank übermittelt werden. Des Öfteren habe ich bereits die Update-Methode des DataAdapters erwähnt, die eine Verbindung zu der Datenbank aufbaut, um deren Datenbestand zu aktualisieren. Vielleicht haben Sie auch schon die Update-Methode nach Änderung der Daten getestet und dabei einen Laufzeitfehler erhalten. Das folgende Beispiel zeigt eine solche Situation, in der eine neue Datenzeile hinzugefügt und eine vorhandene geändert wird. Nach Abschluss der Änderungen wird die Methode Update des DataAdapters aufgerufen.


'...\ADO\Aktualisierung\CommandBuilder.vb

Option Strict On 
Imports System.Data.Common, System.Data.SqlClient 
Namespace ADO 
  Module CommandBuilder 
    ... 
    Sub Test() 
      Dim da As DbDataAdapter, ds As DataSet 
      Lesen(da, ds) 
      Ändern(ds, False) 
      Aktualisieren(da, ds) 
    End Sub

    Sub Lesen(ByRef da As DbDataAdapter, ByRef ds As DataSet) 
      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 ProductID, ProductName, " & _ 
        "UnitsInStock, Discontinued FROM Products" 
      cmd.Connection = conn

      ds = New DataSet() : da = New SqlDataAdapter() 
      da.SelectCommand = cmd 
      da.FillSchema(ds, SchemaType.Source) 
      da.Fill(ds) 
    End Sub

    'neue Datenzeile hinzu und eine andere ändern 
    Sub Ändern(ByVal ds As DataSet, ByVal name As Boolean) 
      Dim neu As DataRow = ds.Tables(0).NewRow() 
      neu("ProductName") = "Camembert" : neu("UnitsInStock") = 100 
      neu("Discontinued") = False 
      ds.Tables(0).Rows.Add(neu) 
      Dim ändern As DataRow = ds.Tables(0).Select("ProductID=14")(0) 
      ändern("UnitsInStock") = CType(ändern("UnitsInStock"), Integer) + 1000 
      If name Then ändern("ProductName") = "Eiweißlieferant" 
    End Sub

    'Datenbank aktualisieren 
    Sub Aktualisieren(ByVal da As DbDataAdapter, ByVal ds As DataSet) 
      Dim betroffen As Integer = 0 
      Try 
        betroffen = da.Update(ds) 
      Catch ex As Exception 
        Console.WriteLine("Fehler: {0}", ex.Message) 
      End Try 
      Console.WriteLine("{0} Datenzeilen aktualisiert", betroffen) 
      Console.ReadLine() 
    End Sub 
  End Module 
End Namespace

Die Ausgabe zeigt einen Laufzeitfehler, der durch Update hervorgerufen wurde.

Fehler: Update requires a valid UpdateCommand when passed DataRow 
collection with modified rows. 
0 Datenzeilen aktualisiert

Um diese Meldung zu verstehen, sehen wir uns an, wie der DataAdapter eine Auswahlabfrage an die Datenbank schickt. Nach (oder bei) der Erzeugung des Command-Objekts wird ein SELECT-Befehl spezifiziert und in der SelectCommand-Eigenschaft des DataAdapters gespeichert.

Der DataAdapter kennt noch drei weitere Kommandos:

  • InsertCommand
  • DeleteCommand
  • UpdateCommand

Analog zum Kommando SelectCommand, das die abzusetzende Auswahlabfrage spezifiziert, benötigt der DataAdapter auch noch Command-Objekte, die die SQL-Befehle INSERT, DELETE und UPDATE beschreiben.

Zum Glück stellt der DataAdapter nicht automatisch Aktualisierungsbefehle bereit, obwohl er das durchaus könnte. Dieser scheinbare Mangel zwingt uns, die benötigten Befehle selbst anzugeben. Und hier wird der Mangel zum Vorteil: Nur der Datenbanknutzer (der Client) weiß, was bei einer Aktualisierung zu tun ist. Jeder Automatismus muss hier über kurz oder lang scheitern, weil er die Logik des Anwendungsprogramms nicht kennen kann.

Der kürzeste Weg zur Spezifikation der notwendigen Aktualisierungslogik ist die Generierung mit einem DbCommandBuilder-Objekt, in dem Sie einen DataAdapter in der gleichnamigen Eigenschaft speichern. Mit dem DataAdapter-Objekt ist auch die SELECT-Auswahlabfrage bekannt. Auf deren Grundlage erzeugt DbCommandBuilder die SQL-Befehle INSERT, DELETE und UPDATE und speichert sie in den entsprechenden Command-Eigenschaften. Wenn im DataSet eine Zeile gelöscht, hinzugefügt oder editiert worden ist, wird der DataAdapter mit den vom DbCommandBuilder erzeugten Kommandos die Originaldatenbank aktualisieren.

Kommen wir zu dem eingangs gezeigten Beispiel zurück. Wenn Sie vor dem Aufruf von Update ein DbCommandBuilder-Objekt erzeugen und initialisieren, wird die Aktualisierung erfolgreich sein. Die folgende Methode Automatisch ersetzt die Methode Test.

Sub Automatisch() 
  Dim da As DbDataAdapter, ds As DataSet 
  Lesen(da, ds) 
  Dim cmb As DbCommandBuilder = New SqlCommandBuilder() 
  cmb.DataAdapter = da 
  Ändern(ds, False) 
  Aktualisieren(da, ds) 
End Sub

Rheinwerk Computing - Zum Seitenanfang

27.1.1 Parallelitätskonflikt Zur nächsten ÜberschriftZur vorigen Überschrift

Als Nächstes simulieren wir einen sogenannten Parallelitätskonflikt. Statt eines einzelnen Benutzers in der Methode Test tauchen in Konflikt zwei Benutzer auf.

Sub Konflikt() 
  Dim da1, da2 As DbDataAdapter, ds1, ds2 As DataSet 
  Lesen(da1, ds1) : Lesen(da2, ds2) 
  Dim cmb1 As DbCommandBuilder = New SqlCommandBuilder() 
  cmb1.DataAdapter = da1 
  Dim cmb2 As DbCommandBuilder = New SqlCommandBuilder() 
  cmb2.DataAdapter = da2 
  Ändern(ds1, True) : Ändern(ds2, False) 
  Aktualisieren(da1, ds1) : Aktualisieren(da2, ds2) 
End Sub

Die Ausgabe zeigt, dass die Aktualisierung des zweiten Benutzers fehlschlägt. Da nur die Methode Aktualisieren eine Ausgabe erzeugt, ist sichergestellt, dass die lokalen Änderungen in der Methode Ändern erfolgreich sind.

2 Datenzeilen aktualisiert

Fehler: Concurrency violation: the UpdateCommand affected 0 
of the expected 1 records. 
0 Datenzeilen aktualisiert

Der Name des Artikels Tofu wird durch den ersten Benutzer geändert (Parameter True in Ändern). Da das DbCommandBuilder-Objekt des zweiten Benutzers davon nichts weiß, wird dessen UPDATE-Befehl nicht der neuen Situation angepasst. Es wird eine Ausnahme vom Typ DBConcurrencyException ausgelöst, obwohl die Primärschlüsselspalte ProductID nicht angetastet wurde. Das automatisch erstellte UPDATE-Kommando stützt sich also nicht auf die Eindeutigkeit der Primärschlüsselspalte, sondern zieht weitere Spaltenwerte zur Identifikation einer Zeile heran.


Rheinwerk Computing - Zum Seitenanfang

27.1.2 Aktualisierungsbefehle des DbCommandBuilders Zur nächsten ÜberschriftZur vorigen Überschrift

Ein DbCommandBuilder erzeugt Aktualisierungscode und nutzt dabei das SELECT-Statement. Doch wie sieht die Aktualisierungslogik exakt aus?

Sie können sich die Aktualisierungsstatements ausgeben lassen, indem Sie die Methoden GetUpdateCommand, GetInsertCommand oder GetDeleteCommand des DbCommandBuilders aufrufen. Alle liefern ein Command-Objekt, über dessen Eigenschaft CommandText Sie den jeweiligen SQL-Befehl abfragen können. Für unser Beispiel:

Sub Kommandos() 
  Dim da As DbDataAdapter, ds As DataSet 
  Lesen(da, ds) 
  Dim cmb As DbCommandBuilder = New SqlCommandBuilder() 
  cmb.DataAdapter = da

  Console.WriteLine(da.SelectCommand.CommandText) 
  Console.WriteLine(cmb.GetInsertCommand().CommandText) 
  Console.WriteLine(cmb.GetDeleteCommand().CommandText) 
  Console.WriteLine(cmb.GetUpdateCommand().CommandText)

  Console.ReadLine() 
End Sub

Die Ausgabe zeigt alle Kommandos:

SELECT ProductID, ProductName, UnitsInStock, Discontinued FROM Products

INSERT INTO [Products] ([ProductName], [UnitsInStock], [Discontinued]) 
VALUES (@p1, @p2, @p3)

DELETE FROM [Products] 
WHERE (([ProductID] = @p1) AND ([ProductName] = @p2) 
  AND ((@p3 = 1 AND [UnitsInStock] IS NULL) OR ([UnitsInStock] = @p4)) 
  AND ([Discontinued] = @p5))

UPDATE [Products] 
SET [ProductName] = @p1, [UnitsInStock] = @p2, [Discontinued] = @p3 
WHERE (([ProductID] = @p4) AND ([ProductName] = @p5) 
  AND ((@p6 = 1 AND [UnitsInStock] IS NULL) OR ([UnitsInStock] = @p7)) 
  AND ([Discontinued] = @p8))

Sie können erkennen, dass hinter der WHERE-Klausel alle Spalten der SELECT-Abfrage als Suchkriterium nach dem zu editierenden Datensatz aufgeführt sind. Der DbCommandBuilder wertet demnach alle Spalten aus und verwendet sie zur Bildung des Command-Objekts.

Die Parameter im SET-Teil werden mit Werten aus DataRowVersion.Current belegt, die im WHERE-Teil aus DataRowVersion.Original.


Rheinwerk Computing - Zum Seitenanfang

27.1.3 Aktualisierungsoptionen des DbCommandBuilders Zur nächsten ÜberschriftZur vorigen Überschrift

ConflictOption

Standardmäßig verwendet der DbCommandBuilder in der WHERE-Klausel für UpdateCommand und DeleteCommand alle zu vergleichenden Spalten. Eine Änderung der Daten in der Datenbank führt zu einer Ausnahme (DBConcurrencyException), wenn ein anderer User eine dieser Spalten in dem Zeitraum verändert hat, in dem die ursprünglichen Daten für die Zeile abgerufen und neue Werte für die Zeile übermittelt werden.

Dieses Verhalten ist nicht immer wünschenswert. Daher stellt Ihnen der DbCommandBuilder mit der Eigenschaft ConflictOption eine Möglichkeit zur Verfügung, das Aktualisierungsverhalten zu beeinflussen. Die Eigenschaft ist vom Typ der gleichnamigen Enumeration, deren Mitglieder Sie Tabelle 27.1 entnehmen können.


Tabelle 27.1 Enumeration »ConflictOption«

Konstante Spalten in WHERE

CompareAllSearchableValues

Alle, nach denen gesucht werden kann (Standard)

CompareRowVersion

Timestamp-Spalte(n), wenn vorhanden (UPDATE), sonst wie OverwriteChanges

OverwriteChanges

Alle Spalten des Primärschlüssels, wenn vorhanden, sonst wie CompareAllSearchableValues


Mit dem Standardwert ConflictOption.CompareAllSearchableValues wird die erste Änderung in einer Datenzeile immer zum Erfolg führen, während folgende Änderungen zu einem Konflikt führen. Dieses Szenario wird daher auch als First-in-wins bezeichnet.

Werden mit ConflictOption.OverwriteChanges nur die Primärschlüsselspalte(n) in die WHERE-Klausel einbezogen, werden Änderungen des ersten Benutzers von den nachfolgenden Änderungen überschrieben. Dieses Szenario wird als Last-in-wins bezeichnet.

Ein Timestamp ist ein automatisch generierter, eindeutiger 8-Byte-Wert. Mithilfe der Timestamp-Spalte einer Zeile können Sie ermitteln, ob ein Wert in der Zeile seit dem Auslesen geändert wurde. Bei jeder Änderung der Zeile wird der Timestamp-Wert aktualisiert. Mit ConflictOption.CompareRowVersion weisen Sie den DbCommandBuilder an, in der WHERE-Klausel nur die Primärschlüsselspalte(n) und die Timestamp-Spalte aufzunehmen.

SetAllValues

Betrachten Sie noch einmal das Beispiel mit Benutzer A und B am Anfang des Kapitels. Es ist denkbar, dass weder das Last-in-wins- noch das First-in-wins-Szenario passend sind. Es können zwei oder mehr Änderungen an einer Datenzeile akzeptiert werden, wenn sie nicht dieselbe Spalte betreffen. Das bedeutet, dass in der WHERE-Klausel neben dem Primärschlüssel auch die jeweils geänderte Spalte mit ihrem Ursprungswert angegeben werden kann. Benutzer A könnte in einem solchen Fall das folgende UPDATE absetzen:

UPDATE Products 
SET ProductName = 'Cheese' 
WHERE ProductID = 55 AND ProductName = 'Käse'

Ändert Benutzer B unter den gleichen Voraussetzungen die Spalte UnitPrice, wird diese seinem UPDATE-Statement hinzugefügt:

UPDATE Products 
SET UnitPrice = 12.98 
WHERE ProductID = 55 AND UnitPrice = 13

Beide Aktualisierungen werden in die Datenbank übernommen.

Setzen Sie die Eigenschaft SetAllValues des DbCommandBuilders auf False, werden neben der Primärschlüsselspalte nur diejenigen Spalten der WHERE-Klausel als Suchkriterium hinzugefügt, deren Inhalte sich verändert haben. Das entspricht genau dem gezeigten Muster.


Rheinwerk Computing - Zum Seitenanfang

27.1.4 Vor- und Nachteile des DbCommandBuilders topZur vorigen Überschrift

Der DbCommandBuilder ist sehr einfach zu handhaben und benötigt nur wenig Programmcode. Der Effizienz bei der Programmierung steht aber ein Performance-Verlust gegenüber. Sie sollten daher in zeitkritischen Anwendungen das Aktualisierungsverhalten nicht vom DbCommandBuilder abhängig machen und, wie gleich gezeigt wird, die Aktualisierungslogik manuell programmieren. Über das Standardverhalten hinaus bietet der DbCommandBuilder eine ganze Reihe von Möglichkeiten, um eine angepasste Konfliktsteuerung zu betreiben. Manchmal wird diese aber nicht ausreichen. Dann heißt es wieder, alles manuell zu codieren.



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