Einführung in den Datenzugriff mit ADO.NET

Bei der Anwendungsentwicklung mit ADO.NET gibt es für die Arbeit mit Daten verschiedene Anforderungen. Manchmal sollen die Daten nur auf einem Formular angezeigt werden. Ein anderes Mal müssen Sie sich eine Lösung ausdenken, mit der Informationen mit einem anderen Unternehmen ausgetauscht werden können.

Unabhängig von der Nutzung der Daten gibt es bestimmte Basiskonzepte, die Sie in Bezug auf die Arbeit mit Daten in ADO.NET verstehen müssen. Möglicherweise benötigen Sie manche Details der Datenbehandlung nie. So kann es z. B. sein, dass Sie eine XML-Datei mit Daten niemals direkt bearbeiten müssen. Es ist aber sehr nützlich, wenn Sie die Datenstruktur in ADO.NET verstehen und wissen, welches die wichtigsten Datenkomponenten sind und wie die einzelnen Teile zusammengehören.

Diese Einführung bietet einen umfassenden Überblick über die wichtigsten Konzepte. In diesem Thema werden viele Details ausgelassen; zu Datasets gäbe es noch einiges mehr zu sagen. Dies geschieht zugunsten einer Einführung in die Konzepte, die hinter der Datenintegration in ADO.NET stehen.

Hinweis   Wenn Sie eine Anwendung weitergeben, die Datenzugriffskomponenten von Visual Studio enthält, vergewissern Sie sich, dass der Benutzer, der die Anwendung installiert, Microsoft Data Access Components (MDAC) Version 2.7 oder höher verwendet. Weitere Informationen finden Sie unter Hinzufügen einer Startbedingung für Microsoft Data Access Components.

ADO.NET ist nicht von permanent aktiven Verbindungen abhängig

Bei konventionellen Client-/Server-Anwendungen stellen die Komponenten eine Verbindung zu einer Datenbank her und erhalten diese so lange aufrecht, bis die Anwendung beendet wird. Aus einer Vielzahl von Gründen ist dieser Ansatz in vielen Anwendungen nicht praktikabel:

  • Offene Datenbankverbindungen belegen wertvolle Systemressourcen. In den meisten Fällen können Datenbanken nur wenige Verbindungen gleichzeitig aufrecht erhalten. Der Aufwand zur Aufrechterhaltung dieser Verbindungen beeinträchtigt die Gesamtleistung der Anwendung.
  • Genauso gestaltet sich die Erweiterung von Anwendungen, die eine offene Datenbankverbindung benötigen, extrem schwierig. Eine Anwendung, die sich nicht leicht nach oben skalieren lässt, mag bei vier Benutzern eine akzeptable Leistung bieten, bei Hunderten von Benutzern ist dies jedoch zweifelhaft. ASP.NET-Webanwendungen im Besonderen müssen leicht skalierbar sein, da sich der Verkehr zu einer Website in einem kurzen Zeitraum aufgrund von erhöhten Bestellungen erhöhen kann.
  • Bei ASP.NET-Webanwendungen sind die Komponenten naturgemäß voneinander getrennt. Der Browser fordert eine Seite vom Server an. Wenn der Server die Seite verarbeitet und gesendet hat, wird erst wieder eine Verbindung zum Browser hergestellt, wenn die nächste Anforderung gestellt wird. Unter diesen Umständen ist es nicht möglich, eine offene Verbindung zu einer Datenbank aufrecht zu erhalten, weil nicht bekannt ist, ob der Datennutzer (der Client) erneut auf Daten zugreifen muss.
  • Bei einem Modell, das auf immer verbundenen Daten basiert, ist es unter Umständen schwierig oder unpraktisch, Daten über Anwendungs- und Unternehmensgrenzen hinweg mit einer verbundenen Architektur auszutauschen. Wenn zwei Komponenten dieselben Daten benötigen, müssen beide verbunden werden. Ansonsten muss eine Lösung gefunden werden, damit die Komponenten Daten hin- und herschicken können.

Aus diesen Gründen ist der Datenzugriff mit ADO.NET um eine Architektur entwickelt, die Verbindungen nur spärlich verwendet. Anwendungen sind gerade so lange mit der Datenbank verbunden, wie für das Abrufen und Aktualisieren der Daten erforderlich ist. Da die Datenbank keine Verbindungen hält, die die meiste Zeit ungenutzt sind, kann sie von viel mehr Benutzern verwendet werden.

Datenbankinteraktionen werden mit Hilfe von Datenbefehlen ausgeführt

Wenn Sie Operationen in einer Datenbank ausführen möchten, führen Sie SQL-Anweisungen oder gespeicherte Prozeduren (die SQL-Anweisungen enthalten) aus. Verwenden Sie SQL-Anweisungen oder gespeicherte Prozeduren, um Zeilen zu lesen und zu schreiben sowie Aggregatfunktionen, wie Hinzufügen oder Durchschnitt errechnen, auszuführen. Verwenden Sie SQL-Anweisungen oder gespeicherte Prozeduren auch, um Tabellen oder Spalten zu erstellen oder zu ändern, Transaktionen auszuführen, usw.

In ADO.NET verwenden Sie Datenbefehle, um eine SQL-Anweisung oder eine gespeicherte Prozedur zu packen. Wenn Sie z. B. einen Zeilensatz aus der Datenbank lesen möchten, erstellen Sie einen Datenbefehl und konfigurieren ihn mit dem Text einer Select-SQL-Anweisung oder dem Namen einer gespeicherten Prozedur, die die Datensätze abruft.

Führen Sie folgende Schritte aus, um die Zeilen aufzurufen:

  1. Öffnen Sie eine Verbindung.
  2. Rufen Sie eine Ausführungsmethode des Befehls auf, die wiederum folgendes ausführt:
    1. Die SQL-Anweisung oder gespeicherte Prozedur wird ausgeführt, auf die der Befehl verweist.

    2. Die Verbindung wird anschließend geschlossen.

      Die Verbindung bleibt nur so lange offen, bis die Anweisung oder die gespeicherte Prozedur ausgeführt wurde.

Wenn Sie die Ausführmethode eines Befehls aufrufen, gibt er einen Wert zurück. Befehle, die die Datenbank aktualisieren, geben die Anzahl der betroffenen Zeilen zurück. Andere Befehlstypen geben einen Fehlercode zurück. Wenn der Befehl die Datenbank mit einer SELECT-Anweisung abfragt, kann der Befehl einen Satz von Zeilen zurückgeben. Sie können diese Zeilen mit einem Datenleser abrufen, der als sehr schneller, schreibgeschützter, vorwärtsgerichteter Cursor fungiert. Weitere Informationen finden Sie unter Abrufen von Daten mit dem DataReader-Objekt.

Sicherheitshinweis   Wenn Sie Datenbefehle mit einer CommandType-Eigenschaft mit dem Wert Text verwenden, müssen Sie die von einem Client gesendeten Informationen sorgfältig überprüfen, bevor Sie diese an die Datenbank übergeben. Böswillige Benutzer könnten versuchen, veränderte oder zusätzliche SQL-Anweisungen zu senden (einzufügen), um unautorisierten Zugriff zu erhalten oder die Datenbank zu beschädigen. Bevor Sie Benutzereingaben an eine Datenbank übergeben, müssen Sie immer die Zulässigkeit der Informationen überprüfen. Es wird empfohlen, möglichst immer parametrisierte Abfragen oder gespeicherte Prozeduren zu verwenden. Weitere Informationen finden Sie unter Skriptangriffe.

Wenn Sie mehrere Operationen ausführen müssen, z. B. einige Zeilen lesen und aktualisieren müssen, verwenden Sie für jede Operation einen Datenbefehl. Jede Operation wird separat ausgeführt. Wenn Sie z. B. die Zeilen lesen möchten, öffnen Sie die Verbindung, lesen die Zeilen und schließen die Verbindung. Wenn Sie Daten aktualisieren möchten, öffnen Sie nochmals die Verbindung, führen die Aktualisierung aus und schließen die Verbindung wieder.

Datenbefehle können Parameter (genauer gesagt eine Auflistung von Parameterobjekten) enthalten, mit denen Sie parametrisierte Abfragen, wie die Folgende, erstellen können:

Select * From customers Where (customer_id = @customerid)

Sie können dann die Parameter zur Laufzeit festlegen und den Befehl ausführen, um die gewünschten Daten zurückzugeben oder zu aktualisieren.

Daten können in Datasets zwischengespeichert werden

Die am häufigsten ausgeführte Aufgabe bei der Arbeit mit Daten ist die Abfrage von Daten aus der Datenbank und deren Bearbeitung: anzeigen, verarbeiten oder an eine andere Komponente senden. Sehr oft muss die Anwendung nicht nur einen Datensatz, sondern eine Gruppe von Datensätzen verarbeiten, wie z. B. eine Liste mit Kunden oder aktuellen Aufträgen. Oftmals stammen die von der Anwendung benötigten Gruppen von Datensätzen aus mehreren Tabellen: Kunden und alle zugehörigen Aufträge, alle Autoren mit dem Namen "Schmidt" und die von ihnen verfassten Bücher sowie andere, ähnliche Gruppen verknüpfter Datensätze.

Sobald diese Datensätze abgerufen wurden, bearbeitet die Anwendung die Datensätze in der Regel als Gruppe. Die Anwendung könnte es dem Benutzer z. B. ermöglichen, alle Autoren mit dem Namen "Schmidt" zu durchsuchen und die Bücher für einen Schmidt anzusehen, um anschließend mit dem nächsten Schmidt fortzufahren usw.

In vielen Fällen ist es nicht praktikabel, jedes Mal zur Datenbank zurückzukehren, wenn die Anwendung den nächsten Datensatz verarbeiten muss. (Denn dadurch geht der Vorteil, dass weniger offene Verbindungen benötigt werden, verloren.) Eine Lösung besteht folglich darin, die von der Datenbank abgerufenen Datensätze vorübergehend zu speichern und mit dieser temporären Gruppe zu arbeiten.

Dies ist unter einem Dataset zu verstehen. Ein Dataset ist ein Cache mit Datensätzen, die aus einer Datenquelle abgerufen wurden. Es funktioniert wie ein virtueller Datenspeicher: Ein Dataset besteht aus einer oder mehreren Tabellen, die auf den Tabellen der tatsächlichen Datenbank basieren. Es kann darüber hinaus Informationen über die Beziehungen zwischen diesen Tabellen sowie Einschränkungen zu den Daten umfassen, die in den Tabellen enthalten sein können.

Die Daten im Dataset sind in der Regel ein Bruchteil dessen, was in der Datenbank enthalten ist. Sie können mit diesen Daten fast genauso wie mit den tatsächlichen Daten arbeiten. Während Sie mit den Daten arbeiten, besteht keine Verbindung zur Datenbank, so dass sie dadurch für andere Aufgaben zur Verfügung steht.

Natürlich müssen Sie die Daten in der Datenbank häufig aktualisieren (jedoch nicht annähernd so oft, wie Daten aus der Datenbank abgerufen werden). Sie können Aktualisierungen am Dataset vornehmen, und die Aktualisierungen anschließend in die zugrunde liegende Datenbank schreiben.

Wichtig ist, dass das Dataset ein passiver Container für die Daten ist. Um Daten tatsächlich aus der Datenbank abzurufen und sie (optional) in die Datenbank zurückzuschreiben, werden Datenadapter verwendet. Ein Datenadapter enthält einen oder mehrere Datenbefehle, die zum Füllen einer einzelnen Tabelle im Dataset und zum Aktualisieren der entsprechenden Tabelle in der Datenbank verwendet wird. (Ein Datenadapter enthält normalerweise vier Befehle: Auswählen, Einfügen, Aktualisieren und Löschen von Zeilen in der Datenbank). Daher könnte die Fill-Methode eines Datenadapters jedes Mal eine SQL-Anweisung wie z. B. SELECT au_id, au_lname, au_fname FROM authors ausführen, wenn die Methode aufgerufen wird.

Da es sich bei einem Dataset tatsächlich um eine private Kopie der Datenbankdaten handelt, spiegelt es den aktuellen Stand der Datenbank nicht unbedingt wider. Wenn Sie sich die letzten Änderungen ansehen möchten, die andere Benutzer vorgenommen haben, können Sie das Dataset aktualisieren, indem Sie die entsprechende Fill-Methode aufrufen.

Einer der Vorteile bei der Verwendung von Datasets besteht darin, dass sie nach Bedarf von Komponenten ausgetauscht werden können. So könnte ein Geschäftsobjekt aus der mittleren Ebene z. B. ein Dataset erstellen und füllen und dieses anschließend zur Verarbeitung an eine andere Komponente senden, die sich an einer anderen Stelle in der Anwendung befindet. Dies bedeutet, dass die Datenbank nicht einzeln von den Komponenten abgefragt werden muss.

Datasets sind von Datenquellen unabhängig

Obwohl ein Dataset als Cache für Daten dient, die aus der Datenbank abgerufen wurden, besteht zwischen Dataset und Datenbank eigentlich keine Beziehung. Das Dataset ist ein Container, der mit Hilfe von SQL-Befehlen oder gespeicherten Prozeduren gefüllt wird, die von einem Datenadapter ausgeführt werden.

Da ein Dataset nicht direkt mit einer Datenquelle verbunden ist, stellt es einen guten Integrationspunkt für Daten dar, die aus mehreren Quellen stammen. Ein Teil der Daten in einem Dataset könnte z. B. aus einer Datenbank stammen, während ein anderer Teil aus einer anderen Datenbank oder einer anderen Quelle kommen könnte, bei der es sich nicht um eine Datenbank handelt (wie z. B. aus einer Tabellenkalkulation). Ein Teil der Daten in einem Dataset könnte in einem Datenstrom empfangen werden, der von einer anderen Komponente gesendet wurde. Sobald sich die Daten in einem Dataset befinden, können Sie mit Hilfe eines konsistenten Objektmodells damit arbeiten, und zwar unabhängig von ihrer ursprünglichen Quelle.

Daten werden im XML-Format gespeichert

Daten müssen vom Datenspeicher zum Dataset und von dort an verschiedene Komponenten gesendet werden. In ADO.NET werden die Daten im XML-Format übertragen. Ebenso werden Daten, wenn diese (z. B. in einer Datei) aufbewahrt werden müssen, im XML-Format gespeichert. Sie können eine XML-Datei wie jede andere Datenquelle verwenden und ein Dataset daraus erstellen.

Tatsächlich ist XML in ADO.NET ein Basisformat für Daten. Die Daten-APIs von ADO.NET erstellen automatisch XML-Dateien oder Datenströme von im Dataset enthaltenen Informationen und senden diese an eine andere Komponente. Die zweite Komponente kann ähnliche APIs aufrufen, um die XML-Dateien wieder in ein Dataset einzulesen. (Die Daten werden im Dataset nicht im XML-Format, sondern in einem effizienteren Format gespeichert. Sie können Daten in einem Dataset z. B. nicht mit einem XML-Parser verarbeiten.)

XML als Grundlage für Datenprotokolle bietet eine Reihe von Vorteilen:

  • XML ist ein Format nach Industriestandard. Das bedeutet, dass die Datenkomponenten Ihrer Anwendung Daten mit jeder anderen Komponente in jeder anderen Anwendung austauschen kann, solange diese Komponente XML versteht. Viele Anwendungen sind so geschrieben, dass sie XML verstehen. Dadurch wird ein noch nie da gewesenes Maß an Austauschbarkeit zwischen völlig verschiedenen Anwendungen erreicht.
  • XML ist textbasiert. Die XML-Darstellung von Daten verwendet keine binären Informationen, so dass sie über jedes Protokoll (z. B. HTTP) verschickt werden können. Die meisten Firewalls blocken binäre Informationen ab. Wenn die Informationen jedoch im XML-Format formatiert sind, können die Informationen trotzdem problemlos zwischen den Komponenten ausgetauscht werden.

In den meisten Fällen müssen Sie XML nicht kennen, um Daten in ADO.NET verwenden zu können. ADO.NET konvertiert Daten nach Bedarf automatisch in das und aus dem XML-Format. Die Interaktion mit den Daten erfolgt über gewöhnliche Programmiermethoden.

Schemas definieren Datenstrukturen

Obwohl Sie sich zum Lesen und Schreiben von Daten in die Datenbank und zum Arbeiten mit Datasets nicht mit XML auskennen müssen, gibt es Situationen, in denen die Arbeit mit XML genau das Ziel ist, das Sie verfolgen. Dies sind Situationen, in denen Sie nicht auf die Daten zugreifen, sondern mit dem Entwurf von Daten arbeiten. Anders ausgedrückt heißt das, dass Sie XML in ADO.NET direkt verwenden, wenn Sie mit Metadaten arbeiten.

Datasets werden im XML-Format dargestellt. Die Struktur des Datasets – die Definition von Tabellen, Spalten, Datentypen, Beschränkungen usw. im Dataset – wird mit einem XML-Schema definiert, das auf der XML Schema Definition (XSD)-Sprache basiert. Genauso wie Daten in einem Dataset aus dem XML-Format geladen und als XML serialisiert werden können, lässt sich die Struktur des Datasets aus einem XML-Schema laden und als XML-Schema serialisieren.

Bei den meisten Aufgaben, die in ADO.NET an Daten ausgeführt werden, müssen Sie sich nicht eingehend mit Schemas befassen. In der Regel werden die Schemas von den Visual Studio .NET-Tools nach Bedarf generiert und aktualisiert, wobei die in visuellen Designern ausgeführten Aufgaben als Grundlage dienen. Wenn Sie z. B. die Tools zum Erstellen eines Datasets verwenden, das Tabellen in Ihrer Datenbank darstellt, generiert Visual Studio .NET ein XML-Schema, das die Struktur des Datasets beschreibt. Das XML-Schema wird anschließend zum Generieren eines typisierten Datasets verwendet, in dem Datenelemente (Tabellen, Spalten usw.) als Member erster Klasse verfügbar sind. Weitere Informationen zu typisierten Datasets finden Sie unter Einführung in Datasets.

Allerdings kann es manchmal vorkommen, dass Sie selbst Schemas erstellen oder bearbeiten möchten. Ein typisches Beispiel ist die Entwicklung eines Schemas zusammen mit einem Partner oder einem Kunden. In diesem Fall wird das Schema als Spezifikation zwischen Ihnen und dem Partner in Bezug auf die Form der XML-basierten Daten verwendet, die ausgetauscht werden. In dieser Situation müssen Sie die Elemente des Schemas oftmals der Struktur Ihrer eigenen Datenbank zuordnen. Weitere Informationen zum Entwerfen von Schemas finden Sie unter XML-Schemas und Daten.

Komponenten von ADO.NET

Die folgende Abbildung zeigt die Hauptkomponenten der ADO.NET-Anwendung.

Datenkomponenten von ADO.NET

In der folgenden Tabelle sind die Datenkomponenten von ADO.NET zusammengefasst, die in der Abbildung oben dargestellt sind. Darüber hinaus enthält sie Links zu weiteren Informationen.

Komponente oder Objekt Weitere Informationen
DataSet Einführung in Datasets
Data adapter Einführung in Datenadapter
Data connection Einführung in die Entwurfstools für ADO.NET-Verbindungen
Windows Form Einführung in Windows Forms
Web Forms-Seite Einführung in Web Forms-Seiten
BizTalk BizTalk-Webseite (https://www.microsoft.com/germany/ms/net-server/biztalkserver/index.htm)

Siehe auch

Vorteile von ADO.NET | Vergleich zwischen ADO.NET und ADO | ADO.NET-Datasets | ADO.NET-Datenadapter | Zugreifen auf Daten mit ADO.NET | XML in Visual Studio | XML-Schemas und Daten