Einführung in ADO.NET - Access im Unternehmen

Werbung
Know-how
Einführung in ADO.NET
Einführung in ADO.NET
Manfred Hoffbauer, Düsseldorf
Die in Microsoft Access integrierte Programmiersprache VBA unterstützt den Zugriff auf AccessDatenbanken 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
Inhalt
1
2
3
4
Achtung: Theorie! ............................................. 1
Von DAO über ADO zu ADO.NET .................. 1
Datenabfrage mit den OleDB-Objekten..... 3
Verbindungslose
Datenzugriffsarchitektur................................ 6
5 Zusammenfassung und Ausblick................11
Zugriff auf die Daten einer Access-Datenbank.
1
2
Achtung: Theorie!
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. „
computer.haufe.de
Von DAO über ADO zu ADO.NET
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 AccessProgrammierer ü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 ServerDatenbanken 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.
2.1 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 .NETDatenproviders den Zugang zu einer Datenquelle.
Abb. 1 zeigt eine Übersicht über die Datenzugriffsobjekte.
Access, SQL & .NET
PREVIEW
1
Know-how
Einführung in ADO.NET
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. „
2.2 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
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 .NETFrameworks 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.
• Microsoft.Jet.OLEDB.4.0: Microsoft JET, also
MDB-Datenbankdateien von Microsoft Access
2.3 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:
step by step
1
Klicken Sie im Startdialog
von SharpDevelop auf den
Button Neues Combine.
2
Markieren Sie die Kategorie VB.NET.
3
Markieren Sie die Schablone Konsolenanwendung.
4
Geben Sie Ado.Jet als
Dateinamen ein.
5
Klicken Sie auf den Button Erstellen. „
Abb. 1: Datenzugriffsobjekte
2
Access, SQL & .NET
PREVIEW
SharpDevelop
erstellt
die
Combine und fügt den Standardcode für eine Konsolenanwendung ein. Durch das Betäti-
computer.haufe.de
Know-how
Einführung in ADO.NET
gen 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 Ordner
Ado.Jet (Sharp Develop) enthaltene Datei
Ado.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.
3
Datenabfrage mit den
OleDB-Objekten
Dieser Beitrag beschäftigt sich mit dem Zugriff
auf Access-Datenbanken. Er geht deshalb vorwiegend auf OleDB und den Zugriff auf AccessDatenbanken 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
Dim cnnString As String
cnnString = "Provider=Microsoft.Jet.OLEDB.4.0;" & _
Mit der Imports-Anweisung
sparen Sie viel Schreibarbeit.
Jetzt können Sie nämlich statt
"Data Source=<Dateipfad>\Adress00.mdb"
Dim cnn As System.Data.
Dim cnn As OleDbConnection
OleDb.OleDbConnection
cnn = New OleDbConnection(cnnString)
cnn.Open()
Quellcode 1
(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.
Abb. 2: Die von SharpDevelop generierte Konsolenanwendung können Sie
sofort starten.
computer.haufe.de
Dieser Variablen weisen Sie den
eigentlichen
ConnectionString zu. Er hat die gleiche
Bedeutung wie bei der Programmierung mit dem herkömmlichen ADO.
Access, SQL & .NET
PREVIEW
3
Know-how
Einführung in ADO.NET
Im Beispiel benennt er den zu verwendenden
Datenprovider und die zu öffnende Access-MDBDatei.
Die zweite Dim-Anweisung definiert ein neues
OleDbConnection-Objekt und weist ihm die
Verbindung zu. Mit cnn.Open() wird die Verbindung geöffnet.
Hinweis
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. „
3.1 Update-, Delete- und InsertAnweisungen per OleDbCommandObjekt 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 DELETEAnweisungen geeignet. Sie ähnelt der Execute-
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
4
Access, SQL & .NET
PREVIEW
computer.haufe.de
Know-how
Einführung in ADO.NET
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.
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 SQLAnweisung 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.
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 OleDBCommandObjektes 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.
3.2 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
Abb. 3: Ausgabe der Vornamen mittels
DataReader-Objekt
Dim strSQL As String
strSQL = "SELECT Vorname, Nachname, Strasse, " _
& "PLZ, Ort FROM tblAdressen;"
Dim cmd As OleDbCommand
Die obige Schleife zeigt alle
Vornamen aus der Adressentabelle an. Zum Schluss des Beispielprogramms sollten Sie die
verwendeten Ressourcen freigeben:
cmd = New OleDbCommand(strSQL, cnn)
reader.Close()
Dim reader As OleDbDataReader
reader = cmd.ExecuteReader()
cnn.Close()
Console.ReadLine()
While reader.Read()
Console.WriteLine(reader("Vorname"))
End While
Quellcode 3
computer.haufe.de
Die Anweisung Console.ReadLine() wartet auf eine Benutzereingabe. Sie hält das Win-
Access, SQL & .NET
PREVIEW
5
Know-how
Einführung in ADO.NET
dows-Befehlszeilenfenster so lange offen, bis Sie
die Eingabetaste betätigen.
4
Verbindungslose
Datenzugriffsarchitektur
Der Datenzugriff mit ADO.NET basiert auf der
verbindungslosen Datenzugriffstruktur. Anders
als bei Microsoft Access üblich werden ein oder
mehrere Datensätze aus einer oder mehreren
Tabellen in den Speicher gelesen, dort bearbeitet
und bei Bedarf die Änderungen geschrieben.
Verbindungslos bedeutet in diesem Fall, dass
nach dem Lesen der Bezug zur Datenquelle vollständig verloren gehen kann. Zur Handhabung
dieser Architektur stellt ADO.NET das DataTableund das DataSet-Objekt zur Verfügung.
Ein DataTable-Objekt besteht aus Zeilen und
Spalten und ist prinzipiell mit einer Datentabelle
vergleichbar. Ein DataSet-Objekt kann aus ein
oder mehreren Tabellen und Relationen bestehen. Ein DataSet ist einerseits mit einer Datenbank vergleichbar, weist aber gleichzeitig gravierende Unterschiede auf. Dadurch bedingt, dass
ein DataSet verbindungslos im Speicher gehalten wird, können die Daten der enthaltenen
Tabellen aus sehr verschiedenen Quellen stammen. So lassen sich in ein und demselben DataSet Datentabellen aus einer Textdatei, einer
Access-Datenbank, einer SQL-Server-Datenbank
und aus weiteren Datenquellen zusammenfügen.
4.1 Daten in ein DataTable lesen
Das DataAdapter-Objekt ist der Vermittler zwischen einem Connection-Objekt und einer DataTable oder einem DataSet. Es enthält die SQLAbfragen, mit denen Sie Daten lesen und schreiben. Das Beispiel aus Quellcode 4 zeigt, wie Sie
die Vornamen aus der Adressentabelle mit Hilfe
eines DataTable-Objektes anzeigen können.
Die Dim-Anweisung definiert das Objekt tblAdressen vom Typ DataTable. Der Variablen wird
gleichzeitig eine neue, leere Instanz des Objekts
zugewiesen.
Die zweite Anweisung definiert ein OleDBDataAdapter-Objekt, das als Vermittler zwischen
der Connection und der DataTable fungiert. Bei
der Definition des OleDBDataAdapter-Objekts
werden eine SELECT-Anweisung und eine Connection angegeben.
Mit adp.Fill(tblAdressen) werden die Daten aus
der Adressentabelle in das DataTable-Objekt
tblAdressen übertragen. Beachten Sie, dass der
Name des DataTable-Objekts frei gewählt werden
kann. Im Beispiel wurde es nur deshalb tblAdressen genannt, damit der Bezug zur Quelltabelle
sofort klar wird. Alternativ könnten Sie das Objekt auch tblX oder einfach
nur Adressen nennen.
Dim tblAdressen As New DataTable
Dim adp As New OleDbDataAdapter("SELECT * FROM tblAdressen", cnn)
adp.Fill(tblAdressen)
Dim row As DataRow
Mit der Fill-Anweisung werden
nicht nur die Daten, sondern es
wird auch die Struktur in das
DataTable-Objekt übertragen.
For Each row In tblAdressen.Rows
Console.WriteLine(row.Item("Vorname"))
Next
Quellcode 4
Dim col As DataColumn
For Each col In tblAdressen.Columns
Console.WriteLine(col.ColumnName.ToString + "->" +
col.DataType.ToString)
Next
Quellcode 5
6
Access, SQL & .NET
PREVIEW
Das Objekt enthält nach der
Zuweisung die gleichen Spalten inklusive Feldnamen, Datentypen und die gleiche Primärschlüsseldefinition wie die
Herkunftstabelle. Die Definition der Spalten können Sie mit
der Schleife aus Quellcode 5
überprüfen.
Die Schleife durchläuft die
Columns-Auflistung
des
computer.haufe.de
Know-how
Einführung in ADO.NET
tblAdressen-Objekts. Zu jeder Spalte werden der
Name und der von .NET zugewiesene Datentyp
angezeigt. Das Ergebnis eines Schleifendurchlaufs sehen Sie in Abb. 4.
der Rows-Auflistung können Sie die Zeilen
durchlaufen und direkt auf die einzelnen Feldwerte zugreifen. Im obigen Beispiel wird exemplarisch der Wert des Feldes Vorname angezeigt.
Der Auflistung in der Abbildung können Sie
entnehmen, wie .NET die in der Access-Tabelle
definierten Datentypen in eigene Datentypen
umsetzt. Zusätzlich zu der Struktur hat die FillMethode auch alle Daten in das DataTableObjekt übernommen. Die einzelnen Datensätze
stellen die Zeilen innerhalb des Objekts dar. Mit
4.2 Daten aktualisieren
Das Aktualisieren der Daten in einem DataTableObjekt erfolgt durch direkte Zuweisung. Mit der
folgenden Anweisung können Sie beispielsweise
den Wert im Feld Vorname des vierten Datensatzes ändern (ohne Zeilenumbruch):
tblAdressen.Rows(3).Item("
Vorname") = "<Unbekannt>"
Beachten Sie dabei, dass die
meisten Indizes in .NET auf 0
basieren. Die erste Zeile erhalten Sie mit Row(0), die zweite
mit Row(1) und so weiter.
Abb. 4: Diese Feldnamen und Datentypen verwendet .NET zur Verwaltung der
Adressentabelle.
Was nutzt das Ändern von
Daten in einem verbindungslosen DataTable-Objekt? Es hat
tatsächlich zunächst keinerlei
Auswirkung auf den zugrunde
liegenden Datenbestand.
Sie können dies leicht prüfen,
indem Sie einige Feldwerte
ändern und dann die folgenden
beiden Anweisungen in das
Programm aufnehmen (ohne
Zeilenumbruch):
Console.WriteLine("<Bitte
betätigen Sie die <Enter>Taste.")
Console.ReadLine()
Abb. 5: Diesen Fehler meldet ADO.NET, falls die zugrunde liegende Datenbank
exklusiv gesperrt wurde.
computer.haufe.de
Wenn Sie das Programm zum
Betätigen der Eingabetaste
auffordert, können Sie die
MDB-Datei öffnen und sich die
Daten ansehen. Sie werden
feststellen, dass keine Änderungen an den Daten durchgeführt wurden. Sie können die
Access, SQL & .NET
PREVIEW
7
Know-how
Einführung in ADO.NET
Datenbank zu diesem Zeitpunkt sogar exklusiv
mit Microsoft Access öffnen. Dies ist gleichzeitig
der Beweis dafür, dass die Verbindung vom DataTable-Objekt zur Datenbank vollständig gelöst
wurde. Um die Daten in der zugrunde liegenden
Datenbank zu aktualisieren, haben Sie prinzipiell
zwei Möglichkeiten.
Sie können die Rows-Auflistung des DataTableObjekts dazu verwenden, für jede geänderte Zeile
eine Update-Anweisung zusammenzusetzen und
diese per OleDBCommand-Objekt auszuführen.
Ob eine Zeile geändert wurde, können Sie mit
der RowState-Eigenschaft abfragen:
die SQL-Anweisungen in der anschließenden
Update-Anweisung verwendet werden. Sie
schreibt die Änderungen in die zugrunde liegende Datentabelle.
Zu diesem Zeitpunkt stellt .NET die Verbindung
zur Datenbank wieder her und versucht, die erforderlichen UPDATE-Anweisungen durchzuführen.
Falls die Access-Datenbank nicht verfügbar oder
exklusiv gesperrt wurde, tritt hierbei ein Fehler
auf. In Abb. 5 sehen Sie, dass sich mit der Fehlermeldung nicht allzu viel anfangen lässt.
If row.RowState=DataRowState.Modified
Then
Dim cb As OleDbCommandBuilder = _
New OleDbCommandBuilder(adp)
...
Try
Die weitaus komfortablere Methode besteht
darin, die beschriebenen Arbeitsschritte dem
DataAdapter-Objekt zu überlassen. Dies ist ein
klassischer Zweizeiler:
Dim cb As OleDbCommandBuilder = New _
OleDbCommandBuilder(adp)
adp.Update(tblAdressen)
Mit der ersten Anweisung definieren Sie ein
OleDBCommandBuilder-Objekt. Durch die Zuweisung mit New OleDBCommandBuilder(adp)
veranlassen Sie .NET, dem OleDBCommandBuilder-Objekt automatisch eine UPDATE-, eine
INSERT- und eine DELETE-Anweisung hinzuzufügen. Da das OleDBCommandBuilder-Objekt
im DataAdapter-Objekt enthalten ist, können
adp.Update(tblAdressen)
Catch exOle As OleDbException
Console.WriteLine(exOle.ToString)
Catch ex As Exception
Console.WriteLine(ex.Message)
End Try
Quellcode 6
Es ist deshalb empfehlenswert, die UpdateAnweisung in einen Try-Catch-Block zu schachteln (s. Quellcode 6). Mit diesen Programmzeilen
erhalten Sie zwar noch keine wirkliche Fehlerbehandlung, Sie erreichen aber immerhin die Anzeige der Fehlermeldung im
Klartext.
Wenn Sie das Programm nun
erneut starten und die AccessDatenbank vor der Ausführung
der Update-Anweisung exklusiv
sperren, dann erhalten Sie die
Anzeige in Abb. 6.
Abb. 6: Mit einem Try-Catch-Block erhalten Sie die Fehlermeldung im Klartext.
8
Access, SQL & .NET
PREVIEW
Die oben beschriebene Vorgehensweise basiert auf einem
automatisch generierten UPDATE-Statement. Mit wenigen
Programmzeilen können Sie
computer.haufe.de
Know-how
Einführung in ADO.NET
4.3 Daten filtern
Ein wichtiger Aspekt beim Abruf von Daten ist die Selektion
der benötigten Datensätze. Im
Hinblick auf die verwendeten
Ressourcen ist es am günstigsten, die Daten direkt bei der
Abfrage zu filtern. Hierzu können Sie das SQL-Statement des
DataAdapter-Objekts mit einer
WHERE-Klausel
ausstatten
(s. Quellcode 8).
Abb. 7: SQL-Text eines UPDATE-Statements
den SQL-Text dieses Statements in die Datei
C:\Test.TXT exportieren lassen (s. Quellcode 7).
Als Ergebnis erhalten Sie die UPDATE-Anweisung
aus Abb. 7.
In diesem Beispiel selektieren
Sie spalten- und zeilenweise. Das Abfrageergebnis enthält nur den Vor- und den Nachnamen
der Adressen aus dem Postleitzahlengebiet 4.
.NET führt diese Anweisung für jede Zeile mit
geänderten Daten einmal aus. Die Fragezeichen
werden dabei durch die Werte der gleichnamigen
Felder aus dem DataTable-Objekt ersetzt.
Dieses Verfahren hat den Nachteil, dass das Filterkriterium statisch in den SQL-String integriert
ist. Wesentlich flexibler ist die Variante, das Filterkriterium als Parameter zu definieren
(s. Quellcode 9).
Das OleDBCommandBuilder-Objekt enthält
ähnliche Anweisungen für die DELETE- und die
INSERT-Anweisung.
Die Verwendung eines benannten Parameters hat
den Vorteil, dass Ihre SQL-Statements besser
lesbar sind. Insbesondere bei komplizierten SQL-
Dim w As New System.IO.StreamWriter("C:\TEST.TXT")
w.Write(cb.GetUpdateCommand().CommandText)
w.Close()
Quellcode 7
strSQL = "SELECT Vorname, Nachname FROM tblAdressen WHERE PLZ LIKE '4%'"
Dim daFilter As New OleDbDataAdapter(strSQL, cnn)
Dim tblLokaleAdressen As New DataTable
daFilter.Fill(tblLokaleAdressen)
For Each row In tblLokaleAdressen.Rows
Console.WriteLine(row.Item("Vorname").ToString + " " + _
row.Item("Nachname").ToString)
Next
tblLokaleAdressen = Nothing
daFilter.Dispose()
Quellcode 8
computer.haufe.de
Access, SQL & .NET
PREVIEW
9
Know-how
Einführung in ADO.NET
strSQL = "SELECT Vorname, Nachname FROM tblAdressen WHERE PLZ = @PLZ"
Dim daParamFilter As New OleDbDataAdapter(strSQL, cnn)
daParamFilter.SelectCommand.Parameters.Add("@PLZ", OleDbType.VarChar, 50).Value = _
"79102"
Dim tblParamAdressen As New DataTable
daParamFilter.Fill(tblParamAdressen)
For Each row In tblParamAdressen.Rows
Console.WriteLine(row.Item("Vorname").ToString + " " + _
row.Item("Nachname").ToString)
Next
tblParamAdressen = Nothing
daParamFilter.Dispose()
Quellcode 9
Dim RowsSelected() As DataRow
RowsSelected = tblAdressen.Select("PLZ = '79102'")
Dim i As Integer
For i = 0 To RowsSelected.Length - 1
Console.WriteLine(RowsSelected(i).Item("Vorname").ToString + " " _
+ RowsSelected(i).Item("Nachname").ToString)
Next
Quellcode 10
Statements oder vielen Parametern helfen Ihnen
benannte Parameter, Programmierfehler zu vermeiden.
niert ein neues DataSet und füllt es mit der
Unternehmens- und der Adressentabelle
(s. Quellcode 11).
Wenn Sie die Daten nicht direkt bei der Abfrage
selektieren können, benutzen Sie am besten die
Select-Methode des DataTable-Objekts.
Im Beispiel fungiert die Unternehmenstabelle als
Mastertabelle. Die Adressentabelle enthält das
Feld UnternehmenID, mit dem eine Adresse
optional einem Masterdatensatz in der Unternehmenstabelle zugeordnet werden kann.
Die Methode selektiert die DataRow-Objekte aus
einem DataTable-Objekt, die dem angegebenen
Filterkriterium entsprechen. Als Ergebnis erhalten
Sie ein Array von DataRow-Objekten mit den
gefundenen Zeilen (s. Quellcode 10).
4.4 Das DataSet-Objekt
Mit dem DataSet-Objekt können Sie mehrere
Datentabellen gleichzeitig im Speicher halten.
Dies hat den Vorteil, dass Sie mehrere relational
verknüpfte Tabellen in einem einzigen Objekt
verwalten können. Das folgende Beispiel defi-
10
Access, SQL & .NET
PREVIEW
Eine solche Relation können Sie dem DataSet
mit
folgenden Anweisungen hinzufügen
(s. Quellcode 12).
Wenn die Relation einmal definiert ist, können
Sie nach Bedarf in den Zeilen der Master- und
der Detailtabelle blättern. Besonders interessant
ist dabei die Möglichkeit, zu einem Datensatz der
Mastertabelle eine Liste der Detaildatensätze
abzufragen. Die GetChildRows-Methode füllt
hierzu ein Array mit den Row-Objekten der
computer.haufe.de
Know-how
Einführung in ADO.NET
Child-Tabelle. Das folgende Beispiel durchläuft
alle Datensätze der Unternehmenstabelle und
zeigt die jeweils zugeordneten Datensätze der
Adressentabelle an (s. Quellcode 13).
5
Zusammenfassung und Ausblick
Der obige Beitrag beschreibt die wichtigsten
Objekte
für
den
Zugriff
auf
MDBDatenbankdateien mit Microsoft .NET. Darüber
hinaus können Sie mit ADO.NET auch auf andere
Datenquellen wie Textdateien, XML-Dateien,
SQL Server-Datenbanken und Oracle-Datenbank
zugreifen. Mit ODBC erschließen Sie sich zudem
ein nahezu unbegrenztes Potenzial an Datenformaten. Die Daten aller Formate lassen sich in
DataTable- und DataSet-Objekte laden und dort
gemeinsam verarbeiten.
Mit diesen Objekten erhalten Sie deshalb einen
relativ hohen Grad der Abstraktion. Aufgrund der
verbindungslosen Speicherung der Daten sind die
Objekte sowohl für Windows- als auch für WebAnwendungen geeignet.
Dim ds As New DataSet
strSQL = "SELECT * FROM tblUnternehmen"
Dim daParent As New OleDbDataAdapter(strSQL, cnnString)
daParent.Fill(ds, "tblUnternehmen")
strSQL = "SELECT * FROM tblAdressen"
Dim daChild As New OleDbDataAdapter(strSQL, cnnString)
daChild.Fill(ds, "tblAdressen")
Quellcode 11
Dim colParent, colChild As DataColumn
colParent = ds.Tables("tblUnternehmen").Columns("UnternehmenID")
colChild = ds.Tables("tblAdressen").Columns("UnternehmenID")
Dim relUnternehmenAdressen As New DataRelation("relUnternehmenAdressen", colParent, _
colChild)
ds.Relations.Add(relUnternehmenAdressen)
Quellcode 12
' Master- und Childatensätze anzeigen
Dim ChildRows() As DataRow
Dim ParentRow As DataRow
Dim i As Integer
For Each ParentRow In ds.Tables("tblUnternehmen").Rows
Console.WriteLine("**** " + ParentRow.Item("Unternehmen").ToString _
+ "**** ")
ChildRows = ParentRow.GetChildRows(relUnternehmenAdressen)
For i = 0 To ChildRows.Length - 1
Console.WriteLine(ChildRows(i).Item("Vorname").ToString + " " + _
ChildRows(i).Item("Nachname").ToString)
Next
Next
Quellcode 13
computer.haufe.de
Access, SQL & .NET
PREVIEW
11
Herunterladen