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 24 Datenbankabfragen mit ADO.NET
Pfeil 24.1 DbCommand
Pfeil 24.1.1 Ein DbCommand-Objekt erzeugen
Pfeil 24.1.2 Ausführen des DbCommand-Objekts
Pfeil 24.1.3 Begrenzung der Abfragezeit durch CommandTimeout
Pfeil 24.1.4 Aktionsabfragen absetzen
Pfeil 24.1.5 Abfragen mit einem Einzelergebnis
Pfeil 24.2 SqlDataReader
Pfeil 24.2.1 Das SQL-Kommando SELECT
Pfeil 24.2.2 Datensätze einlesen
Pfeil 24.2.3 DataReader schließen
Pfeil 24.2.4 MARS (Multiple Active Resultsets)
Pfeil 24.2.5 Batch-Abfragen mit NextResult durchlaufen
Pfeil 24.2.6 Informationen über eine Tabelle
Pfeil 24.3 Parametrisierte Abfragen
Pfeil 24.3.1 SqlClient-Datenprovider
Pfeil 24.3.2 SqlParameter
Pfeil 24.3.3 OleDb-Datenprovider
Pfeil 24.4 Asynchrone Abfragen
Pfeil 24.4.1 Polling
Pfeil 24.4.2 Bereitstellen einer Rückrufmethode
Pfeil 24.5 Gespeicherte Prozeduren (Stored Procedures)
Pfeil 24.5.1 Gespeicherte Prozeduren in Visual Studio 2008 erstellen
Pfeil 24.5.2 Gespeicherte Prozeduren aufrufen
Pfeil 24.5.3 Komplexe gespeicherte Prozeduren

In diesem Kapitel wird gezeigt, wie eine Datenbank verändert und ausgelesen wird. Weitere Themen sind das Auslesen der Datenbankstruktur und gespeicherte Prozeduren auf dem Datenbankserver.

24 Datenbankabfragen mit ADO.NET

Voraussetzung jeder Datenbankabfrage ist die Verbindung zu der Datenquelle. Wie Sie das Connection-Objekt dazu erzeugen, habe ich im letzten Kapitel gezeigt. Nun gehen wir den nächsten Schritt und widmen uns dem Abruf von Daten aus der Datenbank. Ich erkläre auch, wie Daten in der Originaldatenbank verändert, hinzugefügt und gelöscht werden. Für solche Operationen stellt ADO.NET eine weitere Klasse zur Verfügung, die je nach eingesetztem Datenprovider SqlCommand, OleDbCommand oder OdbcCommand heißt. Command-Objekte sind auf die Verbindung zum Datenbankserver angewiesen. Der folgende Ausschnitt aus der Vererbungshierarchie zeigt, dass Sie durch eine Beschränkung auf die Funktionen der Klassen DbCommand und DbCommandBuilder leicht zu einem anderen Datenbankprovider wechseln können.

System.Object 
 +System.MarshalByRefObject 
   +System.ComponentModel.Component 
     +System.Data.Common.DbCommand 
     | +System.Data.Odbc.OdbcCommand 
     | +System.Data.OleDb.OleDbCommand 
     | +System.Data.OracleClient.OracleCommand 
     | +System.Data.SqlClient.SqlCommand 
     | +System.Data.SqlServerCe.SqlCeCommand 
     +System.Data.Common.DbCommandBuilder 
       +System.Data.Odbc.OdbcCommandBuilder 
       +System.Data.OleDb.OleDbCommandBuilder 
       +System.Data.OracleClient.OracleCommandBuilder 
       +System.Data.SqlClient.SqlCommandBuilder 
       +System.Data.SqlServerCe.SqlCeCommandBuilder

Neben der Klasse DbCommand werden Sie weitere wichtige Klassen kennenlernen, allen voran die Klasse DbDataReader, die die Datensätze einer Ergebnisliste durchläuft oder Schemainformationen einer Tabelle abruft. DbDataReader ist tatsächlich in der gesamten ADO.NET-Klassenbibliothek die einzige Klasse, die Dateninformationen abrufen kann. Auch wenn wir uns später mit der Klasse DbDataAdapter beschäftigen, die über die Methode Fill ein DataSet zu füllen vermag, hält der DbDataReader im Hintergrund die Fäden in der Hand. Von außen betrachtet, können wir das allerdings nicht direkt erkennen. Am Ende des ADO.NET-Teils dieses Buches werden Sie noch einmal dem DbCommand-Objekt begegnen, wenn wir abweichend von der Standardvorgabe unsere eigene Aktualisierungslogik codieren. Auch bei diesen anderen Klassen lohnt sich eine Beschränkung auf Klassen des Namensraums System.Data. Common, um einen Wechsel des Datenbankproviders zu erleichtern.

System.Object 
 +System.MarshalByRefObject 
   +System.ComponentModel.Component 
   | +System.Data.Common.DataAdapter 
   |   +System.Data.Common.DbDataAdapter 
   |     +Microsoft.AnalysisServices.AdomdClient.AdomdDataAdapter 
   |     +System.Data.Odbc.OdbcDataAdapter 
   |     +System.Data.OleDb.OleDbDataAdapter 
   |     +System.Data.OracleClient.OracleDataAdapter 
   |     +System.Data.SqlClient.SqlDataAdapter 
   |     +System.Data.SqlServerCe.SqlCeDataAdapter 
   +System.Data.Common.DbDataReader 
     +System.Data.DataTableReader 
     +System.Data.Odbc.OdbcDataReader 
     +System.Data.OleDb.OleDbDataReader 
     +3System.Data.OracleClient.OracleDataReader 
     +System.Data.SqlClient.SqlDataReader 
     +System.Data.SqlServerCe.SqlCeDataReader 
       +System.Data.SqlServerCe.SqlCeResultSet

Hinweis
Wenn möglich werden die Db- statt der Sql-Typen verwendet. Alle Aussagen, die sich im Folgenden auf die Db-Typen beziehen, gelten auch für die analogen Sql-Typen.



Rheinwerk Computing - Zum Seitenanfang

24.1 DbCommand Zur nächsten ÜberschriftZur vorigen Überschrift

Das DbCommand-Objekt repräsentiert einen SQL-Befehl oder eine gespeicherte Prozedur. In der Eigenschaft CommandText wird die SQL-Anweisung bzw. die gespeicherte Prozedur festgelegt. Die Ausführung wird mit einer der Execute-Methoden gestartet. Die Klasse DbCommand selbst ist abstrakt, und die Objekterzeugung erfolgt über eine providerspezifische Klasse, zum Beispiel SqlCommand.

Als kleinen Vorgeschmack möchte ich Ihnen ein Beispiel zeigen. Darin wird die Verbindung zu der Beispieldatenbank Northwind des SQL Servers aufgebaut. In der Tabelle Products, in der alle Artikel geführt sind, ist unter anderem ein Artikel mit der Bezeichnung Chai (Spalte ProductName) gespeichert. Nehmen wir an, dieser sei falsch und soll nun in Tee geändert werden. Dazu übergeben wir der Eigenschaft CommandText des DbCommand-Objekts ein entsprechendes UPDATE-Kommando und führen es mit ExecuteNonQuery aus.


'...\ADO\Datenbankabfragen\Command.vb

Option Strict On 
Imports System.Data.Common 
Imports System.Data.SqlClient 
Namespace ADO 
  Module Command 
    Sub Test()

      Dim con As DbConnection = New SqlConnection() 
      con.ConnectionString = "Data Source=(local);" & _ 
          "Initial Catalog=Northwind;Integrated Security=sspi"

      Dim cmd As DbCommand = New SqlCommand() 
      cmd.CommandText = "UPDATE Products " & _ 
        "SET ProductName='Tee' WHERE ProductName='Chai'" 
      cmd.Connection = con

      con.Open()

      cmd.ExecuteNonQuery()

      con.Close() 
      Console.ReadLine() 
    End Sub 
  End Module 
End Namespace

Hinweis
Wenn Sie in UPDATE die WHERE-Klausel vergessen, werden alle Zeilen geändert.


Vom Erfolg der Operation können Sie sich auf verschiedene Weisen überzeugen. Sie könnten sich einerseits mit dem Tool SQL Server Management Studio von SQL Server den Inhalt der nun geänderten Tabelle anzeigen lassen. Sie können das aber auch aus dem Server-Explorer des Visual Studio heraus, den Sie über das Menü Ansicht öffnen. Fügen Sie über das Kontextmenü des Knotens Datenverbindungen die Verbindung zu der Datenbank Northwind hinzu. Ein Assistent, den wir uns später noch genauer ansehen werden, führt Sie durch den gesamten Verbindungsprozess, an dessen Ende Sie die Möglichkeit haben, sich den aktuellen Inhalt der Tabelle Products in Visual Studio anzeigen zu lassen.


Rheinwerk Computing - Zum Seitenanfang

24.1.1 Ein DbCommand-Objekt erzeugen Zur nächsten ÜberschriftZur vorigen Überschrift

Um ein Kommando gegen eine Datenbank abzusetzen, wird ein DbCommand-Objekt benötigt. Dies trifft für eine Auswahlabfrage (SELECT) ebenso zu wie für eine Aktionsabfrage (INSERT, UPDATE oder DELETE). Das SQL-Kommando wird der Eigenschaft CommandText des DbCommand-Objekts zugewiesen. Zusätzlich zum Befehl muss das DbCommand-Objekt auch den Datenbankserver und die Datenbank kennen, das heißt, es muss wissen, welches DbConnection-Objekt die Verbindung zur Datenbank beschreibt.

Um diese Anforderungen zu erfüllen, stehen Ihnen mehrere Konstruktoren zur Verfügung. Verwenden Sie den parameterlosen Konstruktor, müssen Sie der Eigenschaft Connection des DbCommand-Objekts die Referenz auf ein DbConnection-Objekt zuweisen. Einer anderen Konstruktorüberladung können Sie neben der Referenz auf das SqlConnection-Objekt auch das abzusetzende Kommando als Zeichenfolge übergeben.

Dim cmd As DbCommand = New SqlCommand("UPDATE Products " & _ 
   "SET ProductName='Tee' WHERE ProductName='Chai'")

Eine zweite Variante zur Erzeugung eines DbCommand-Objekts ruft die Methode CreateCommand eines DbConnection-Objekts auf.

Dim con As DbConnection = New SqlConnection("...") 
Dim cmd As DbCommand = con.CreateCommand()

Hinweis
Wenn Sie eine provider-spezifische Verbindung verwenden, ist das Command-Objekt auch provider-spezifisch.



Rheinwerk Computing - Zum Seitenanfang

24.1.2 Ausführen des DbCommand-Objekts Zur nächsten ÜberschriftZur vorigen Überschrift

Die CommandText-Eigenschaft legt das Kommando fest, das ausgeführt werden soll. Es kann sich dabei um ein SQL-Kommando oder eine gespeicherte Prozedur handeln. Bei den SQL-Kommandos werden zwei Kategorien unterschieden:

  • Auswahlabfragen
  • Aktionsabfragen

Eine Auswahlabfrage verwendet die SELECT-Klausel und liefert immer ein Ergebnis zurück, im Fall einer Aggregatfunktion wie SUM oder COUNT liefert sie aber nur einen Ergebniswert. Eine typische Auswahlabfrage wäre zum Beispiel:

SELECT ProductName, UnitPrice FROM Products WHERE UnitPrice < 100

Das Resultat dieser Abfrage bilden alle Datensätze der Tabelle Northwind, die diejenigen Produkte beschreiben, deren Preis kleiner 100 ist.

Eine Aktionsabfrage manipuliert die Datenbank. Dabei kann es sich um die

  • Aktualisierung der Daten (DML-Abfrage = Data Manipulation Language-Abfrage) oder um die
  • Änderung der Datenbankstruktur (DDL-Abfrage = Data Definition Language-Abfrage)

handeln. Mit

UPDATE Products 
SET ProductName='Tee' 
WHERE ProductName='Chai'

haben wir eingangs eine DML-Abfrage abgesetzt, die zwar einen Datensatz in Products ändert, aber die geänderten Daten nicht zurückgibt, sondern nur die Anzahl Änderungen.

Wie Sie sehen, führt das Absetzen eines Befehls zu ganz unterschiedlichen Reaktionen des Datenbankservers. Das SqlCommand-Objekt trägt dem Rechnung und stellt mit

  • ExecuteNonQuery
  • ExecuteReader
  • ExecuteScalar
  • ExecuteXmlReader

vier Methoden zur Verfügung, die speziell auf die einzelnen Abfragen abgestimmt sind. Die ersten drei sind auch in DbCommand enthalten. Alle Methoden werden synchron ausgeführt. Synchron bedeutet, dass die Clientanwendung nach dem Methodenaufruf so lange wartet, bis das Ergebnis der Anfrage vom Datenbankserver eintrifft. Gegebenenfalls kann das eine längere Zeitspanne beanspruchen. Sie können aber Datenbankabfragen auch asynchron ausführen. Der Client muss dann nicht warten, bis die Abfrageausführung beendet ist, sondern kann weiterarbeiten, bis ihm signalisiert wird, dass die Ergebnisse vollständig vorliegen. Entsprechende asynchrone Methoden werden vom Command-Objekt bereitgestellt.


Rheinwerk Computing - Zum Seitenanfang

24.1.3 Begrenzung der Abfragezeit durch CommandTimeout Zur nächsten ÜberschriftZur vorigen Überschrift

Wird eine Abfrage mit ExcuteScalar, EcexuteNonQuery oder ExcuteReader ausgeführt, wartet das SqlCommand-Objekt per Vorgabe 30 Sekunden auf das Eintreffen der ersten Abfrageergebnisse (andere Provider können unterschiedliche Zeiten festlegen). Das Überschreiten der eingestellten Zeit hat zur Folge, dass eine Ausnahme ausgelöst wird.

Mit der Eigenschaft CommandTimeout kann die Voreinstellung verändert werden. Mit der Einstellung »0« wartet das SqlCommand-Objekt eine unbegrenzte Zeit. Dies ist problematisch, da eine Abfrage durch einen Fehler »unendlich« lange dauern kann. Die Zeit für eine Abfrage beginnt mit dem Senden des Kommandos an den Server und endet mit der Serverantwort.


Rheinwerk Computing - Zum Seitenanfang

24.1.4 Aktionsabfragen absetzen Zur nächsten ÜberschriftZur vorigen Überschrift

Abfragen, die Änderungen an den Originaldaten der Datenbank nach sich ziehen (UPDATE, DELETE, INSERT) oder die Struktur einer Datenbank verändern (z. B. CREATE TABLE), werden mit der Methode ExecuteNonQuery abgesetzt.


Public MustOverride Function ExecuteNonQuery() As Integer

Handelt es sich bei dem Befehl um ein UPDATE-, INSERT- oder DELETE-Kommando, stellt der Rückgabewert die Anzahl der von der Anweisung betroffenen Datenzeilen dar.

Datensätze hinzufügen

In der folgenden SQL-Syntax passen Sie die kursiven Namen Ihren Bedürfnissen an (optionale Teile stehen in eckigen Klammern, und Alternativen werden durch | getrennt).


INSERT [INTO] Tabelle[(Spalten)] (VALUES(Werte) | SELECT... | EXECUTE...)

Das folgende Beispielprogramm fügt der Tabelle Products einen Datensatz hinzu. Dabei wird der parametrisierte Konstruktor der Klasse SqlCommand verwendet, der im ersten Parameter den SQL-Befehl und im zweiten die Referenz auf das SqlConnection-Objekt entgegennimmt (DbConnection geht nicht).


'...\ADO\Datenbankabfragen\Insert.vb

Option Strict On 
Imports System.Data.Common, System.Data.SqlClient 
Namespace ADO 
  Module Insert 
    Sub Test() 
      Dim SqlCon As SqlConnection = New SqlConnection("Data Source=.;" & _ 
          "Initial Catalog=Northwind;Integrated Security=sspi") 
      Dim SQL_Befehl As String = _ 
         "INSERT INTO Products(ProductName, Discontinued) " & _ 
         "VALUES('Schweizer Käse',0)" 
      Try 
        Dim cmd As DbCommand = New SqlCommand(SQL_Befehl, SqlCon) 
        SqlCon.Open() 
        Dim zeilen As Integer = cmd.ExecuteNonQuery() 
        Console.WriteLine("{0} Zeile(n) geändert.", zeilen) 
      Catch ex As Exception 
        Console.WriteLine("Fehler: {0}", ex.Message) 
      Finally 
        SqlCon.Close() 
      End Try 
      Console.ReadLine() 
    End Sub 
  End Module 
End Namespace

Die Ausgabe bestätigt das Einfügen:

1 Zeile(n) geändert.

Datensätze löschen

In der folgenden SQL-Syntax passen Sie die kursiven Namen Ihren Bedürfnissen an (optionale Teile stehen in eckigen Klammern):


DELETE [FROM] Tabelle [WHERE Bedingung]

Der Datensatz aus dem vorhergehenden Beispiel soll nun wieder gelöscht werden, und zwar zweifach:


'...\ADO\Datenbankabfragen\Delete.vb

Option Strict On 
Imports System.Data.Common, System.Data.SqlClient 
Namespace ADO 
  Module Delete 
    Sub Test() 
      Dim SqlCon As SqlConnection = New SqlConnection("Data Source=.;" & _ 
          "Initial Catalog=Northwind;Integrated Security=sspi") 
      Dim SQL_Befehl As String = _ 
         "DELETE FROM Products WHERE ProductName='Schweizer Käse'" 
      Try 
        Dim cmd As DbCommand = New SqlCommand(SQL_Befehl, SqlCon) 
        SqlCon.Open() 
        Console.WriteLine("{0} Zeile(n) geändert.", cmd.ExecuteNonQuery()) 
        Console.WriteLine("{0} Zeile(n) geändert.", cmd.ExecuteNonQuery()) 
      Catch ex As Exception 
        Console.WriteLine("Fehler: {0}", ex.Message) 
      Finally 
        SqlCon.Close() 
      End Try 
      Console.ReadLine() 
    End Sub 
  End Module 
End Namespace

Hinweis
Wenn Sie in DELETE die WHERE-Klausel vergessen, wird alles gelöscht.


Nach dem ersten Löschbefehl befindet sich kein der WHERE-Klausel entsprechender Datensatz mehr in der Tabelle, und es wird nichts weiter gelöscht.

1 Zeile(n) geändert. 
0 Zeile(n) geändert.

Datensätze ändern

In der folgenden SQL-Syntax passen Sie die kursiven Namen Ihren Bedürfnissen an (optionale Teile stehen in eckigen Klammern, und Alternativen werden durch | getrennt).


UPDATE Tabelle SET Spalte=Wert 
  [(WHERE (Bedingung | CURRENT OF cursor) | FROM TabelleX WHERE Bedingung)]

Zu Beginn dieses Abschnitts wurde in dem Beispiel Command bereits gezeigt, wie Sie Datensätze in der Datenbank editieren können.


Rheinwerk Computing - Zum Seitenanfang

24.1.5 Abfragen mit einem Einzelergebnis topZur vorigen Überschrift

Mit der SELECT-Anweisung können Sie Datensätze nach bestimmten Auswahlkriterien aus einer Datenbank abrufen. Der Befehl SELECT wird aber auch dann benutzt, wenn eine Aggregatfunktion definiert werden soll, die ein einzelnes Ergebnis zurückliefert. Beispielsweise können Sie mit dem Aggregat

SELECT COUNT(*) FROM Products

die Anzahl der Artikel in der Tabelle Products ermitteln und mit

SELECT COUNT(*) FROM Products WHERE CategoryID = 1

feststellen, wie viele Artikel zur Kategorie 1 gehören. Tabelle 24.1 zeigt die fünf Standardaggregatfunktionen:


Tabelle 24.1 Aggregatfunktionen

Funktion(Spalten) Beschreibung

COUNT

Anzahl der Werte in der Spalte

SUM

Summe der Werte in der Spalte

AVG

Mittelwert der Spalte

MAX

Größter Wert in der Spalte

MIN

Kleinster Wert in der Spalte


Um den Rückgabewert einer Aggregatfunktion entgegenzunehmen, rufen Sie die Methode ExecuteScalar des SqlCommand-Objekts auf. Der Typ der Rückgabe ist Object, daher muss das Ergebnis noch in den passenden Datentyp konvertiert werden.

Dim strSQL As String = "SELECT COUNT(*) FROM Products WHERE CategoryID=1" 
Dim cmd As DbCommand = new SqlCommand(strSQL, SqlCon) 
Dim anzahlDS As Integer = Convert.ToInt32(cmd.ExecuteScalar())


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