ADO.NET
Ralf Westphal
Freier Fachautor & Berater
MSDN Regional Director
[email protected]
Ausgangsfrage

Wie wollen Sie in OO-Programmen auf
Ihre Daten zugreifen?
•
•
Per relationalem Datenzugriffs-API
•
Cursor, Join etc.
Per Objektmodell
•
Objekte, „Collections“, Hierarchien
Sind Datenbanksysteme nötig?

Kann Datenverwaltung nicht über
Objektmodelle stattfinden?
•
•
•

Intuitive Abbildung der „realen Welt“
Einfache zu Traversieren/Manipulieren
1 Datenmodell für persistente Daten und inmemory Datenverwaltung, statt 2
Probleme
•
•
•
•
Persistenz
Abfragen
Gleichzeitiger Zugriff
Große Datenmengen
Lösungen

Lösungen für mögl. Probleme mit
Objektmodellen für die Datenhaltung
•
•
•
•
Persistenz
•
Serialisierung (.NET Formatter)
Abfrage
•
•
Deklarative Abfragesprache
Meta-Objektmodell
Gleichzeitiger Zugriff
•
•
(Objektmodell-)Server
Clients cachen Daten
Große Datenmengen
•
Server mit beliebiger interner Datendarstellung
Fazit



Datenbanken sind notwendig
•
Wertvolle Dienstleistungen
•
Transaktionen, gleichzeitiger Zugriff,
Verwaltung großer Datenmengen, Replikation
usw.
Objektmodelle stehen nicht im
Gegensatz zu Datenbanken
Wir brauchen...
•
•
ein vernünftiges Meta-Objektmodell
ein zum Meta-Objektmodell passenden
Datenbankzugriffs-APIs
ADO.NET Grundlagen
ADO.NET Architektur
VS .NET
Designers
“<xml>
…
</xml>”
Web/Windows
Form Controls
myDataSet
<xml>
…
</xml>
Cust
Order
Item
VS .NET Class
Generator
Managed Provider
DataAdapter
DataReader
Command
Connection
String Stream
XmlReader
TextReader
XmlText- XmlNodeReader
Reader
XmlDocument
ADO vs ADO .NET
ein Überblick der Änderungen







COM Marshalling
Connection oriented
OLE DB Provider
Zwei mögliche
Programmiermod.:
• ADO
• OLE DB nativ
Cursor
Joins für > 1 Tabelle
Datentypen von
COM/COM+ abhängig







COM+, Datasets
Disconnected Access
Managed Providers
Ein Modell:
• Managed Provider
(connected Layer)
• DataSet (discon.)
(Kein Cursor)
Kein Join notwendig
XML, keine Datentypen
Konvertierung nötig
Managed Providers



Interaktion mit Datenquellen „managen“
Äquivalent des OLE DB Layers
•
Direkte Darstellung des Consumer Interfaces (nicht
mehr mit der Zweiteilung COM/Automation)
Aktuelle Implementierungen
•
•
•
OleDB Managed Provider (ähnlich ADO)
•
Zugriff auf beliebige OLE DB Provider
SQLServer Managed Provider
Weitere folgen
•
•
Data
Provider
ODBC
SQL XML
Data
store
Einbindung in die Objekthierarchie
...
System.Data
System.Data.OleDb
System.Data.SqlClient
...
System.Data
System.Data.OleDb
System.Data.SqlClient
DataRelation
OleDbConnection
SqlConnection
DataSet
OleDbCommand
SqlCommand
DataTable
OleDbDataReader
SqlDataReader
DataRow
OleDbParameter
SqlParameter
DataColumn
OleDbDataAdapter
SqlDataAdapter
DataSetView
OleDbErrors
SqlErrors
...
...
ADO.NET Objekt Model


Das klassische ADO Gewand …
•
•
Connection
Command, Parameter
… mit neuen Objekten:
•
•
•
DataReader
•
Forward-only, Read-only „Recordset“
DataSet
•
Disconnected, In-Memory Cache
DataAdapter
•
Verbindet das DataSet mit der Datenquelle
Connection Objekt


Repräsentation einer Verbindung
zu einer Datenquelle
Mit einer Connection ist es möglich …
•
•

Die Verbindung zur Datenquelle
anzupassen
Transaktionen zu handhaben
(Begin, Commit, Abort)
Ähnlichkeiten zum ADODB.Connection
Objekt sind nicht unerwünscht 
Connection Objekt
// Angabe des Namespace (System.Data.SQL)
Using System.Data.SqlClient;
// Instanziieren eines SQLConnection Objekts
SqlConnection cnn = new SqlConnection();
// Connection String setzen
cnn.ConnectionString =
"server=localhost;uid=sa;database=pubs";
// Öffnen der Connection
cnn.Open();
Command Objekt


Stellt ein auszuführendes Kommando dar
•
Mit dem ADO .NET Command Objekt ist es möglich:
•
•
•


Nicht unbedingt ein SQL Kommando
Ein Statement, welches auf dem Server
ausgeführt werden soll, zu definieren
Parameter Informationen für dieses Kommando anzugeben
Rückgabewerte nach der Kommandoausführung zu erhalten
Wie das ADODB.Command Objekt
Kann Parameter enthalten
•
Werte, die bei Ausführung eines Statements genutzt werden
können
Command Objekt
// Create Command
SqlCommand cmd = new SqlCommand();
// Aktive Connection des Kommandos und Inhalt setzen
cmd.ActiveConnection = cnn;
cmd.CommandText = "Select au_lname from authors where
state = @param1";
// Parameter erzeugen und Werte setzen
cmd.Parameters.Add(
new SQLParameter("@param1", typeof(String),2) );
cmd.Parameters["@param1"].Value = "CA";
DataReader

Der DataReader bietet einen forward-only, read-only
Datenstrom
•


Stellt die Ergebnisse einer ausgeführten
Abfrage/Kommandos dar
Der DataReader bietet die Möglichkeit …
•
Einen Ergebnis-Datenstrom
von einer Datenquelle zu erhalten
Gleichbedeutend mit einem FO/RO RecordSet
•
•
Unterstützt jedoch weder Scrolling noch Updates
Auf Felder greift man am besten mit Hilfe von Accessoren
(strongly typed, indexed) zu, die FieldsCollection ist die
schlechtere Möglichkeit
•
•

Performance

myRow.GetInt(0)
Zugriff über den Feldnamen (einfache Nutzung/Kompatibilität)

myRow["fieldname"]
Unterstützung von DataBinding in WebForms
DataReader Verwendung
// DataReader Definieren
IDataReader dr;
// Kommando ausführen
cmd.Execute(out dr);
// Ergebnisse auslesen
while(dr.Read())
{
Console.WriteLine("Name = " + dr["au_lname"]);
}
// Connection schließen
cnn.Close();
DataSet
Common client data store



Relationale Sicht der Daten
•
Tabellen, Spalten, Zeilen,
Beschränkungen, Beziehungen
Direkte Erzeugung von Metadaten
einfaches Einfügen von Daten
Explizites Cache Modell
•
•
•
•
DataSet
Tables
Table
Columns
Column
Constraints
Constraint
Rows
Relations
Row
Relation
Disconnected, remotable Objekt
Hat keine Kenntnis über die Datenquelle oder deren
Eigenschaften
Zugriff wie auf ein Array
Strong Typing möglich
DataSet
// Erzeugen eines DataSet "PublicSet"
DataSet pubs = new DataSet(" PublicSet");
//Erzeugen einer Tabelle “bestand"
DataTable inventory = new DataTable(“bestand");
inventory.Columns.Add(“kennzeichenID",typeof(Int32));
inventory.Columns.Add(“menge",typeof(Int32));
// Tabelle “Bestand” zum DataSet PublicSet hinzufügen
pubs.Tables.Add(bestand);
// Datensatz zur Bestandstabelle hinzufügen
DataRow row = bestand.NewRow();
row[“kennzeichenID"]=1;
row[“menge"]=25;
bestand.Rows.Add(row);
(Strongly) Typed DataSet

DataSets, Tabellen, Zeilen als Objekte
nutzen
•
Spalten und Beziehungen als Eigenschaften
//Ausgabe jedes Autors und dessen Titel
foreach (Author myAuthor in Pubs.Authors.Rows)
{
Console.WriteLine("Name = " + myAuthor.au_lname);
foreach (Title myTitle in myAuthor.Titles)
{
Console.WriteLine("Title = " + myAuthor.Title);
}
}
DataAdapter

Weiß, wie eine Tabelle aus der Datenbank
geladen wird und schreibt Änderungen
zurück
•
•
•
•
•
Fill(DataSet)
Update(DataSet)
Mapping zwischen Tabellen und Spalten
Benutzer kann die voreingestellten Kommandos
überschreiben (insert/update/delete)
•
•
z. B. um Stored Procedures anzugeben
Default-Kommandos mit CommandBuilder erzeugen
Erlaubt es, ein DataSet aus mehreren
Datenquellen zu füllen
DataAdapter
// Neues DataSetCommand
SqlDataAdapter dsAdap = new SqlDataAdapter(
"Select * from authors",cnn);
// Daten an ein DataSet übergeben
dsAdap.Fill(pubs, "Authors");
// Änderungen in den Kundendaten des DataSets durchführen
und Update durchführen
pubs.Tables["Authors"].Rows[0]["au_lname"]="smith";
SqlCommandBuilder bld = new SqlCommandBuilder(dsAdap);
dsAdap.Update(pubs, "Authors");
DataBinding

DataView
•
•
•
•

Wie ein View auf eine Tabelle
Erlaubt, Sortierreihenfolge und Filter in einem View einer
Tabelle festzulegen
Beliebige DataViews können von einer Tabelle erzeugt
werden, um unterschiedliche Views der gleichen Tabelle
möglich zu machen
Wird für das DataBinding verwendet
DataSetView
•
•
•
•
Wie ein View, daß auf einem DataSet aufsetzt
Sortierreihenfolge und Filter lassen sich setzen
Erlaubt das Verbinden von DataViews
Wird für das Databinding verwendet
DataBinding

Als Quelle für DataBinding dienen:
•
•
•
•
•
•
•
•
•
(DataReader)
DataTable
DataView
DataSet
DatSetView
Array
Collection
IList
IEnumerable
Zusammenfassung

ADO .NET ist die natürliche Weiterentwicklung
von ADO
•
•
Bekanntes Connection/Command Modell
Teilung von Persistenz und Programmierung
•
•



Optimierter ForwardOnly/ReadOnly
Ergebnis-Datenstrom
Expliziter, nicht verbundener relationaler Cache
ADO .NET ist XML optimiert
ADO .NET ist im .NET Framework integriert
•
Exception Handling, Namensgebung, Notierung
Bessere plattformübergreifende Zusammenarbeit und
Sharing der Daten, bessere Skalierbarkeit, strong
typing
ADO.NET Anwendungen
Überblick

Szenen eines Datenzugriffs
•
•
•
Aufwärmen:
•
•
•
AutoNumber-Felder
Logisches Löschen
Joins & DataSets
Jetzt wird es ernst:
•
•
Hierarchische Daten laden
Logisches Sperren
Cool down:
•
Eigene Datenquellen anbinden
AutoNumber-Felder
 AutoNumber-Information
wird nicht
autom. geladen
• Steht erst nach DataAdapter.FillSchema zur
Verfügung
 DataColumn.AutoIncrementSeed/.AutoIn
crementStep müssen gesetzt werden
 AutoNumber-Werte in DataTable können
nicht in AutoNumber-DB-Felder
persistiert werden
• Fremdschlüssel geraten aus dem Tritt
 Fazit:
AutoNumber-Felder vermeiden!
Logisches Löschen


Ein Datensatz wird im DataSet gelöscht,
in der Datenbank jedoch nur als
gelöscht markiert
Lösung:
•
•
Tabelle mit einer Spalte für ein
Löschkennzeichen ausstatten
DataAdapter mit speziellem
Löschkommando ausstatten
•
Update mytable set [email protected] where
[email protected]
Joins & DataSets


Einsatz bisher
•
•
Anbinden von untergeordneten Informationen (Master/Detail)
Anbinden von Lookup-Informationen
Kein (semi)automatischer Update
•
CommandBuilder generiert keine DML-Anweisungen für
DataTables mit mehreren Tabellen
 Das ist gut so!

Einsatz mit DataSets
•
•

Untergeordnete Informationen über Relationen anbinden
•
•
Es müssen mehrere Select-Anweisungen ausgeführt werden
Where-Klauseln untergeordneter Select-Anweisungen müssen
Where-Klauseln übergeordneter enthalten
Lookup-Informationen entweder auch über Relationen oder
weiterhin über Joins anbinden
Fazit: Joins verlieren mit DataSets an Bedeutung
•
Joins sind oft keine natürliche Darstellung von
Datenbeziehungen
Hierarchische Daten laden

Hierarchische Daten bilden oft eine
logische Einheit: „Dokumente“
•
•

DB-APIs kennen keine „Dokumente“
Daten in „Dokument“-Granularität zu laden,
entlastet Netzwerkverbindungen
CRUD-Szenarien profitieren vom
Denken in „Dokumenten“
•
•
•
„Dokumente“ definieren...
Zugriff per „Dokument“-ID (PK des
Wurzeldatensatzes)
„Dokumente“ mit eigenem API verwalten...
Hierarchische Daten laden
Hierarchische Daten laden
 Mögliche
„Dokument“-Definition
<table name="customer" basetable="customers" fields="*"
pk="custID" checkOutOk="1">
<table name="invoices" basetable="invoices"
fields="*" pk="invID" checkOutOk="1">
<table name="lineItems" basetable="invoiceLineItems"
fields="*" pk="invLIID">
<lookup basetable="products" fields="description,
price"
pk="prodID"/>
<column name="total" type="System.Double"
expression="qty*price"/>
</table>
<column name="total" type="System.Double„
expression="sum(child(lineItems).total)"/>
</table>
<table name="comm" basetable="customercommunication"
fields="telID, custID, tel" pk="telID"/>
</table>
Hierarchische Daten laden


Rudimentärer „Dokument“-API
•
•
•
•
DataSet CreateDocument()
DataSet GetDocument(string id)
StoreDocument(doc as DataSet)
DeleteDocument(string id)
ToDos
•
•
•
•
„Dokument“-Definition zuordnen
DB-Anbindung
Validation?
Logisches Sperren?
Logisches Sperren


Sperren von Datensätzen während einer
(lange andauernden) Bearbeitung
Probates Mittel: physikalisches Sperren
via DB-API
•
•

Das ist immer falsch!
ADO.NET bietet dafür keine Mittel
Lösung: Logisches Sperren
•
Sperrungen werden durch Anwendung
verwaltet
•
Z.B. im Hauptspeicher, spezielle Tabelle
Logisches Sperren

Herausforderungen
•
Sicherstellen, dass alle Beteiligten die
logischen Sperren beachten
•
•
•
•
Datenzugriff darf nicht mehr direkt stattfinden,
sondern nur über einen dedizierten API
Wer (ent)sperrt wann?
Was passiert mit „zu lange“ gesperrten
Daten?
•
Z.B. weil der Client abgestürzt ist
Performantes Sperren vs „dauerhaftes“
Sperren
Eigene Datenquellen anbinden

DataSets werden über Managed Provider
gefüllt
•
•

Managed Provider Klassen
•
•
•

DataSets sind unabhängig von Datenquellen
Managed Provider sind nicht auf Datenbanken
festgelegt
Datenquelle anbinden/manipulieren: Connection,
Command
Datenquelle lesen: DataReader, DataAdapter
Datenquelle aktualisieren: DataAdapter
A Simple Managed Provider
•
Realisierung eines eigenen DataAdapter ist
ausreichend
•
Implementiert IDataAdapter
Fazit

ADO.NET zwingt zum Umdenken
•
•
•
•
Es gibt (fast) keine Cursor mehr
•
DataSets sind in-memory Datencaches
DataSets unterstützen eine oft natürlichere Sicht
auf Daten
ADO.NET bietet kaum „Infrastruktur“ für einige
typische Probleme
•
•

DataReader ist heute eine „Ausnahme“
„Dokument“-Handling

SQL XML .NET Klassen mögen helfen
Logisches Sperren
Die Zukunft?
•
•
ResultSets
ObjectSpaces: OR-Mapping
Fragen!?
Uff...
ADO .NET Quellen












Jetzt lerne ich ADO.NET
Ralf Westphal, 400 Seiten, Markt+Technik, 2002 (noch nicht erschienen)
ADO .NET for the ADO Programmer
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dndotnet/html/adonetdev.asp
ADO.NET : Migrating from beta 1 to beta 2
http://www.asptoday.com/content/articles/20010802.asp?WROXEMPTOKEN=934243ZaVjEiid0J0l
7LCYvBGK
Coping with a New Beta - Connecting to Databases
http://www.dotnetjunkies.com/tutorials.aspx?tutorialid=81
Coping with a New Beta - DataSetCommand to DataAdapter
http://www.dotnetjunkies.com/tutorials.aspx?tutorialid=83
Using ADO+ and C# in the .NET Framework - Part 1
http://www.asptoday.com/content/articles/20000925.asp?WROXEMPTOKEN=934243ZaVjEiid0J0l
7LCYvBGK
Using ADO+ and C# in the .NET Framework - Part 2
http://www.asptoday.com/content/articles/20000925.asp?WROXEMPTOKEN=934243ZaVjEiid0J0l
7LCYvBGK
Revisiting the Use of ADO in .NET Applications
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dndive/html/data08092001.asp
Commands in ADO .NET
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dndive/html/data07262001.asp
Data Relations and Relatives
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dndive/html/data07122001.asp
Views and Filters
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dndive/html/data06142001.asp
Paradigmenwechsel mit ADO.NET
http://www.microsoft.com/germany/ms/msdnbiblio/kolumne/062001rw.htm
Über den Referenten
Ralf Westphal ist freier Softwaretechnologievermittler. Er arbeitet als Fachautor,
Coach/Berater, Softwareentwickler und Sprecher auf Konferenzen im In- und Ausland
wie Microsoft Technical Summit, XML-in-Action, BASTA!, COMDEX, Software
Development oder XML One.
Der Schwerpunkt seiner Arbeit liegt bei der Vermittlung und Anwendung moderner
Softwaretechnologien und -konzepte auf der Microsoft Plattform mit Fokus in den
Bereichen OOP/komponentenorientierte Entwicklung, Softwarearchitektur und .NET
Framework.
Darüber hinaus ist Ralf Westphal einer der deutschen Microsoft MSDN Regional
Directors, Mitglied verschiedener Fachbeiräte und war von 1998 bis 2001
Chefredakteur der Visual Basic Fachzeitschrift BasicPro.
Bücher des Referenten
.NET kompakt
140 Seiten, Spektrum Akademischer Verlag, 2002, ISBN
3827411858
Jetzt lerne ich ADO.NET
Einfache Datenbankprogrammierung im .NETFramework
400 Seiten, Markt+Technik, 2002, ISBN 3827262291 (erscheint
Mitte 2002)
Empower people
through great software
any time, any place,
and on any device