ADO.NET – eine Einführung

Manfred Hoffbauer, Düsseldorf

Die in Microsoft Access integrierte Programmiersprache VBA unterstützt den Zugriff auf Access-Datenbanken per DAO und ADO. Auch in Microsoft Visual Basic.NET ist mit ADO.NET eine Technik für den Zugriff auf solche Datenbanken enthalten. Der folgende Beitrag beschreibt die wichtigsten Techniken für den lesenden und schreibenden Zugriff auf die Daten einer Access-Datenbank.

Einer der Gründe für den Erfolg von Access ist, dass man auch mit wenigen Kenntnissen schnell achtbare Ergebnisse erzielt und alle notwendigen Hilfsmittel in einer einzigen Anwendung findet. Für die Erstellung einer Anwendung auf Basis der .NET-Technologien bedarf es weit mehr: Dazu sind Kenntnisse in Winforms oder ASP.NET, ADO.NET und einer .NET-Programmiersprache wie C#.NET oder VB.NET erforderlich.

Da der vorliegende Beitrag aber “nur” eine Einführung in ADO.NET geben möchte, sind die Beispiele auf das Mindeste reduziert – sie haben keine Benutzeroberfläche und auch die Ausgabe der Ergebnisse erfolgt lediglich per Konsole. Alles andere hätte auch den Rahmen gesprengt und zu sehr vom eigentlichen Thema abgelenkt. Dafür lernen Sie aber alle wichtigen Techniken für den Zugriff auf eine Access-Datenbank per ADO.NET kennen und können diese Kenntnisse später leicht aufgreifen, wenn Sie einmal eine “richtige” .NET-Anwendung mit Benutzeroberfläche erstellen.

Hinweis

Die Beispieldaten befinden sich auf der Heft-CD in der Zip-Datei ADO.NET.zip. Als Beispieldatenbank dient die Adressverwaltung, die Sie unter dem Dateinamen Adress97.mdb bzw. Adress00.mdb auf der Heft-CD finden. Den kompletten Code mit allen Beispielen enthält die Datei Main.vb.

Schon seit mehreren Jahren beherrscht Access neben DAO ein weiteres Verfahren für den Datenzugriff. Mit den so genannten Active Data Objects (kurz: ADO) verfügt der Access-Programmierer über ein modernes Verfahren für den Datenzugriff. Zahlreiche Beiträge von Access im Unternehmen haben sich mit den Vor- und Nachteilen von ADO und DAO beschäftigt. Einer der wichtigsten Vorteile von ADO besteht wohl darin, dass Sie mit dieser Technik sowohl auf Access-Datenbanken als auch auf SQL Server-Datenbanken zugreifen können. Microsoft selbst weist immer wieder darauf hin, dass DAO und ADO bei der Programmierung mit Access ihre Berechtigung haben. Je nach Anwendung ist die eine oder die andere Zugriffstechnik besser geeignet.

ADO.NET

Die mit .NET eingeführte Methode für den Datenzugriff nennt Microsoft ADO.NET. Wie der Name schon verrät, hat ADO.NET mehr ähnlichkeiten mit ADO als mit DAO. Access-Programmierer, die bisher vorwiegend mit DAO gearbeitet haben, müssen sich also umstellen. Wie bei ADO basiert bei ADO.NET der gesamte Datenzugriff auf einem Connection-Objekt. Mit ihm öffnen Sie unter Verwendung eines .NET-Datenproviders den Zugang zu einer Datenquelle. Abb. 1 zeigt eine übersicht über die Datenzugriffsobjekte.

Hinweis

Im Zusammenhang mit ADO.NET ist von Objekten wie Connection, DataCommand und DataAdapter die Rede. Tatsächlich sind diese Objekte in Microsoft.NET gar nicht vorhanden. Es handelt sich lediglich um Oberbegriffe für die je nach verwendeter Technik dedizierten Objekte. Bei Verwendung von OleDB verwenden Sie die Objekte OleDBConnection, OleDbCommand und OleDBDataAdapter. Diese Objekte befinden sich im Namespace System.Data.OleDB.

Abb. 1: Datenzugriffsobjekte

Im Namespace System.Data.SqlClient ist der Datenprovider für SQL Server-Datenbanken (ab Version 7.0) enthalten.

Im Namespace System.Data.OleDB ist der Datenprovider für andere Datenquellen enthalten. Seit der Version 1.1 des Microsoft .NET-Frameworks befinden sich im Namespace System.Data.ODBC die Objekte für den Zugriff mit der ältesten der drei Techniken. Bei Version 1.0 des .NET-Frameworks musste der ODBC-Provider nachträglich installiert werden.

Der OleDbConnection-String

Die Anforderungen an den ConnectionString variieren stark zwischen SqlClient, OleDB und ODBC. Speziell beim OleDBConnection-String können Sie innerhalb des Strings einen Datenprovider spezifizieren.

Mögliche Einträge lauten wie folgt:

  • SQLOLEDB: SQL Server ab Version 6.5
  • MSDAORA: Oracle-Datenbanken
  • Microsoft.Jet.OLEDB.4.0: Microsoft JET, also MDB-Datenbankdateien von Microsoft Access
  • Combine anlegen

    Um die Beispiele aus diesem Beitrag nachzuvollziehen, sollten Sie mit SharpDevelop (Beschreibung und Download siehe Ausgabe 4/2004, Beitrag .Net-Programmierung mit SharpDevelop) eine neue Combine anlegen.

    Starten Sie das Programm und gehen Sie wie folgt vor:

  • Klicken Sie im Startdialog von SharpDevelop auf den Button Neues Combine.
  • Markieren Sie die Kategorie VB.NET.
  • Markieren Sie die Schablone Konsolenanwendung.
  • Geben Sie Ado.Jet als Dateinamen ein.
  • Klicken Sie auf den Button Erstellen. (
  • SharpDevelop erstellt die Combine und fügt den Standardcode für eine Konsolenanwendung ein. Durch das Betätigen der F5-Taste können Sie das Programm sofort starten.

    Hinweis

    Wenn Sie die nachfolgenden Beispiele einfach nur nachvollziehen und nicht selbst eingeben möchten, können Sie nach dem öffnen von SharpDevelop auch direkt auf die Schaltfläche Combine öffnen klicken und die im OrdnerAdo.Jet (Sharp Develop) enthaltene DateiAdo.Jet.cmbx auswählen. Die Prozedur Main enthält alle nachfolgend beschriebenen Beispiele; nach dem Betätigen von F5 durchläuft die Prozedur nacheinander die Beispiele.

    Wie Sie in Abb. 2 erkennen können, führt Windows die Konsolenanwendung im Fenster des Befehlszeileninterpreters aus. Durch das Betätigen einer beliebigen Taste können Sie die Anwendung beenden, was wiederum zum automatischen Schließen des Befehlszeileninterpreterfensters führt.

    Dieser Typ Anwendung eignet sich gut, um Techniken wie beispielsweise den Datenzugriff unabhängig von irgendwelchen Fragen der Benutzeroberfläche zu testen.

    Dim cnnString As String
    cnnString = "Provider=Microsoft.Jet.OLEDB.4.0;" & _
        "Data Source=<Dateipfad>\\Adress00.mdb"
    Dim cnn As OleDbConnection
    cnn = New OleDbConnection(cnnString)
    cnn.Open()

    Quellcode 1

    Abb. 2: Die von SharpDevelop generierte Konsolenanwendung können Sie sofort starten.

    Dieser Beitrag beschäftigt sich mit dem Zugriff auf Access-Datenbanken. Er geht deshalb vorwiegend auf OleDB und den Zugriff auf Access-Datenbanken ein. Die hierfür benötigten Objekte befinden sich im Namespace System.Data.OleDB.

    Um auf ein Objekt aus diesem Namespace zuzugreifen, können Sie ihm die Bezeichnung des Namespaces voranstellen oder Sie schreiben einmal zu Beginn Ihres Programms die folgende Anweisung:

    Imports System.Data.OleDb

    Mit der Imports-Anweisung sparen Sie viel Schreibarbeit. Jetzt können Sie nämlich statt

    Dim cnn As System.Data.OleDb.OleDbConnection

    (ohne Zeilenumbruch) vereinfacht Folgendes schreiben:

    Dim cnn As OleDbConnection

    Hierfür benötigen Sie eine Verbindung, die Sie wie in Quellcode 1 erzeugen und öffnen können.

    Mit der Dim-Anweisung definieren Sie die String-Variable cnnString.

    Dieser Variablen weisen Sie den eigentlichen Connection-String zu. Er hat die gleiche Bedeutung wie bei der Programmierung mit dem herkömmlichen ADO.

    Sub Main()
        Dim cnnString As String
        cnnString = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\\Nordwind.mdb"
        Dim cnn As OleDbConnection
        cnn = New OleDbConnection(cnnString)
        cnn.Open()
        Dim cmdUDI As OleDbCommand
        cmdUDI = New OleDbCommand("UPDATE Personal SET Vorname = ''''Hans'''' " _        & "WHERE Vorname = ''''Andrew''''", cnn)
        console.writeline("Anzahl geänderter Datensätze: " + _        cmdUDI.ExecuteNonQuery().ToString)
        cmdUDI = New OleDbCommand("INSERT INTO Personal ( Vorname, Nachname ) VALUES " _        & "(''''Manfred'''', ''''Hoffbauer'''' )", cnn)
        console.writeline("Anzahl hinzugefügter Datensätze: " + cmdUDI.ExecuteNonQuery()
        cmdUDI = New OleDbCommand("DELETE FROM Personal WHERE Vorname = ''''Manfred'''' " _        & "AND Nachname = ''''Hoffbauer''''", cnn)
        Console.WriteLine("Anzahl Deletes: " + cmdUDI.ExecuteNonQuery().ToString)
        cmdUDI = New OleDbCommand("SELECT COUNT(*) FROM Personal", cnn)
        Console.WriteLine("Anzahl Mitarbeiter: " + cmdUDI.ExecuteScalar().ToString)
        cnn.Close
    End Sub

    Quellcode 2

    Im Beispiel benennt er den zu verwendenden Datenprovider und die zu öffnende Access-MDB-Datei.

    Die zweite Dim-Anweisung definiert ein neues OleDbConnection-Objekt und weist ihm die Verbindung zu. Mit cnn.Open() wird die Verbindung geöffnet.

    Wenn Sie statt auf einen OleDB-Provider auf einen SQL-Provider zugreifen wollen, dann verwenden Sie statt des OleDBConnection- ein SqlConnection-Objekt. Beide Begriffe werden in der Fachliteratur als DataConnection zusammengefasst. Objekte können aber nur den Typ OleDBConnection oder SqlConnection und nicht den Type DataConnection haben.

    Update-, Delete- und Insert-Anweisungen per OleDbCommand-Objekt ausführen

    Eine Connection an sich ist keine wirkliche Errungenschaft, aber die notwendige Voraussetzung für weitere Verfahren des Datenzugriffs. Basierend auf einer OleDBConnection können Sie ein OleDBCommand-Objekt definieren.

    Das OleDBCommand-Objekt verfügt über die drei folgenden Methoden:

  • ExecuteNonQuery: Mit dieser Anweisung können Sie SQL-Anweisungen ausführen, die keine Rückgabewerte haben. Beispiele sind INSERT, UPDATE und DELETE. Die Methode gibt die Anzahl der betroffenen Datensätze zurück.
  • ExecuteScalar: Mit dieser Methode können Sie SQL-Anweisungen ausführen, die einen einzelnen Rückgabewert erfordern (zum Beispiel die Anzahl der betroffenen Datensätze).
  • ExecuteReader: Mit dieser Methode erhalten Sie ein DataReader-Objekt mit dem Ergebnis Ihrer Abfrage. Damit können Sie etwa die per SELECT-Anweisung ermittelten Datensätze lesen.
  • Die ExecuteNonQuery-Methode ist zur Ausführung von INSERT-, UPDATE- und DELETE-Anweisungen geeignet. Sie ähnelt der Execute-Methode von Access. Die Anzahl der von einer Aktion betroffenen Datensätze erhalten Sie als Funktionsargument zurück. Betrachten Sie dazu die Routine aus Quellcode 2.

    Dim strSQL As String
    strSQL = "SELECT Vorname, Nachname, Strasse, " _    & "PLZ, Ort FROM tblAdressen;"
    Dim cmd As OleDbCommand
    cmd = New OleDbCommand(strSQL, cnn)
    Dim reader As OleDbDataReader
    reader = cmd.ExecuteReader()
    While reader.Read()
        Console.WriteLine(reader("Vorname"))
    End While

    Quellcode 3

    Die Dim-Anweisung definiert das Objekt cmdUDI mit dem Typ OleDBCommand. Die anschließende Zuweisung weist dem Objekt ein neues Command-Objekt mit der jeweils angegebenen SQL-Anweisung zu. Die Angabe der Verbindung bestimmt, auf welcher Datenbank die SQL-Anweisung ausgeführt wird.

    Die Methode cmdUDI.ExectureNonQuery() führt die SQL-Anweisung aus. Bei allen Aktionsabfragen wird die Anzahl der betroffenen Datensätze per Console.WriteLine() angezeigt. Die Methode cmdUDI.ExecuteScalar() führt die SELECT-Anweisung aus und gibt den Wert der ersten Spalte der ersten Zeile des Abfrageergebnisses als Wert zurück. Im Beispiel entspricht dies der Anzahl der Datensätze aus der Tabelle Personal.

    Daten per SELECT-Anweisung lesen

    Mit der ExecuteReader-Methode können Sie ein DataReader-Objekt erzeugen lassen. Mit dem DataReader-Objekt können Sie die Daten einer Abfrage vorwärts gerichtet lesen. Das Verhalten des Objekts entspricht daher ein wenig dem sequenziellen Lesen von Daten aus einer Textdatei. Das DataReader-Objekt hält immer nur einen Datensatz im Speicher und spart deshalb Ressourcen. Gleichzeitig benötigt es die Verbindung aber während seiner gesamten Lebensdauer exklusiv. Das Beispiel aus Quellcode 3 zeigt das satzweise Lesen von Adressen mit dem DataReader-Objekt.

    Sie können eine Objektvariable vom Typ DataReader nicht direkt mit New instanzieren. Ein DataReader-Objekt kann nur mittels der ExecuteReader-Methode eines OleDBCommand-Objektes erzeugt werden.

    Im Beispiel wird eine SELECT-Abfrage auf die Adresstabelle durchgeführt. Die Read-Methode des DataReader-Objektes gibt den Wert True zurück, wenn ein Datensatz gelesen werden konnte.

    Andernfalls gibt die Methode den Wert False zurück. Mit dem DataReader-Objekt können Sie unter Angabe des Feldnamens direkt auf die einzelnen Spaltenwerte zugreifen.

    Abb. 3 zeigt exemplarisch die Anzeige der Vornamen aus der Adressentabelle.

    Abb. 3: Ausgabe der Vornamen mittels DataReader-Objekt

    Die obige Schleife zeigt alle Vornamen aus der Adressentabelle an. Zum Schluss des Beispielprogramms sollten Sie die verwendeten Ressourcen freigeben:

    reader.Close()
    cnn.Close()
    Console.ReadLine()

    Die Anweisung Console.ReadLine() wartet auf eine Benutzereingabe. Sie hält das Windows-Befehlszeilenfenster so lange offen, bis Sie die Eingabetaste betätigen.

    Ende des frei verfügbaren Teil. Wenn Du mehr lesen möchtest, hole Dir ...

    den kompletten Artikel im PDF-Format mit Beispieldatenbank

    diesen und alle anderen Artikel mit dem Jahresabo

    Schreibe einen Kommentar