ADO.NET Ralf Westphal Freier Fachautor & Berater MSDN Regional Director ralfw@ralfw.de.

Post on 05-Apr-2015

110 views 4 download

transcript

ADO.NET

Ralf WestphalFreier Fachautor & BeraterMSDN Regional Director

ralfw@ralfw.de

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 in-memory 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

Managed ProviderManaged Provider

Data-Data-AdapterAdapter

DataReaderDataReader

CommandCommandConnectionConnection

XmlReaderXmlReader

XmlText-XmlText-ReaderReader

XmlNode-XmlNode-ReaderReader XmlDocumentXmlDocumentTextReaderTextReader

StringString StreamStream

<xml><xml>……

</xml></xml>

““<xml><xml>……

</xml>”</xml>”

myDataSetmyDataSet

ItemItem

CustCustOrderOrder

Web/Windows Web/Windows Form ControlsForm ControlsVS .NET VS .NET

DesignersDesignersVS .NET Class VS .NET Class

GeneratorGenerator

ADO vs ADO .NETein Ü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• ODBC

• SQL XML

Data Data storestore

DataDataProviderProvider

Einbindung in die Objekthierarchie

...System.DataSystem.Data.OleDbSystem.Data.SqlClient...

System.Data

DataSet

DataTable

DataColumn

DataRow

DataSetView

DataRelation

System.Data.OleDb

OleDbCommand

OleDbDataReader

OleDbDataAdapter

OleDbParameter

OleDbErrors

OleDbConnection

...

System.Data.SqlClient

SqlCommand

SqlDataReader

SqlDataAdapter

SqlParameter

SqlErrors

SqlConnection

...

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

// Angabe des Namespace (System.Data.SQL)// Angabe des Namespace (System.Data.SQL)Using System.Data.SqlClient;Using System.Data.SqlClient;

// Instanziieren eines SQLConnection Objekts// Instanziieren eines SQLConnection ObjektsSqlConnection cnn = new SqlConnection();SqlConnection cnn = new SqlConnection();

// Connection String setzen// Connection String setzencnn.ConnectionString = cnn.ConnectionString = "server=localhost;uid=sa;database=pubs";"server=localhost;uid=sa;database=pubs";

// Öffnen der Connection// Öffnen der Connectioncnn.Open();cnn.Open();

Connection Objekt

Command Objekt

Stellt ein auszuführendes Kommando dar• Nicht unbedingt ein SQL Kommando

Mit dem ADO .NET Command Objekt ist es möglich:• 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

// 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";

Command Objekt

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 DefinierenIDataReader dr;

// Kommando ausführencmd.Execute(out dr);

// Ergebnisse auslesenwhile(dr.Read()){

Console.WriteLine("Name = " + dr["au_lname"]);}

// Connection schließencnn.Close();

DataReader Verwendung

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• Disconnected, remotable Objekt

• Hat keine Kenntnis über die Datenquelle oder deren Eigenschaften

• Zugriff wie auf ein Array

• Strong Typing möglich

DataSetDataSet

TablesTables

TableTable

ColumnsColumns

ColumnColumnConstraintsConstraints

ConstraintConstraintRowsRows

RowRowRelationsRelations

RelationRelation

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//Ausgabe jedes Autors und dessen Titel foreach (Author myAuthor in Pubs.Authors.Rows) foreach (Author myAuthor in Pubs.Authors.Rows) {{ Console.WriteLine("Name = " + myAuthor.au_lname);Console.WriteLine("Name = " + myAuthor.au_lname); foreach (Title myTitle in myAuthor.Titles)foreach (Title myTitle in myAuthor.Titles) {{

Console.WriteLine("Title = " + myAuthor.Title);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ügungDataColumn.AutoIncrementSeed/.AutoIn

crementStep müssen gesetzt werdenAutoNumber-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 delFlag=@delFlag where

pk=@pk

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• DataSets sind unabhängig von Datenquellen

• Managed Provider sind nicht auf Datenbanken festgelegt

Managed Provider Klassen• 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

• DataReader ist heute eine „Ausnahme“

• 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• „Dokument“-Handling

SQL XML .NET Klassen mögen helfen

• Logisches Sperren Die Zukunft?

• ResultSets

• ObjectSpaces: OR-Mapping

Fragen!?

Uff...Uff...

ADO .NET Quellen

Jetzt lerne ich ADO.NETRalf Westphal, 400 Seiten, Markt+Technik, 2002 (noch nicht erschienen)

ADO .NET for the ADO Programmerhttp://msdn.microsoft.com/library/default.asp?url=/library/en-us/dndotnet/html/adonetdev.asp

ADO.NET : Migrating from beta 1 to beta 2http://www.asptoday.com/content/articles/20010802.asp?WROXEMPTOKEN=934243ZaVjEiid0J0l7LCYvBGK

Coping with a New Beta - Connecting to Databaseshttp://www.dotnetjunkies.com/tutorials.aspx?tutorialid=81

Coping with a New Beta - DataSetCommand to DataAdapterhttp://www.dotnetjunkies.com/tutorials.aspx?tutorialid=83

Using ADO+ and C# in the .NET Framework - Part 1http://www.asptoday.com/content/articles/20000925.asp?WROXEMPTOKEN=934243ZaVjEiid0J0l7LCYvBGK

Using ADO+ and C# in the .NET Framework - Part 2http://www.asptoday.com/content/articles/20000925.asp?WROXEMPTOKEN=934243ZaVjEiid0J0l7LCYvBGK

Revisiting the Use of ADO in .NET Applicationshttp://msdn.microsoft.com/library/default.asp?url=/library/en-us/dndive/html/data08092001.asp

Commands in ADO .NEThttp://msdn.microsoft.com/library/default.asp?url=/library/en-us/dndive/html/data07262001.asp

Data Relations and Relativeshttp://msdn.microsoft.com/library/default.asp?url=/library/en-us/dndive/html/data07122001.asp

Views and Filtershttp://msdn.microsoft.com/library/default.asp?url=/library/en-us/dndive/html/data06142001.asp

Paradigmenwechsel mit ADO.NEThttp://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 kompakt140 Seiten, Spektrum Akademischer Verlag, 2002, ISBN 3827411858

Jetzt lerne ich ADO.NETEinfache Datenbankprogrammierung im .NET- Framework400 Seiten, Markt+Technik, 2002, ISBN 3827262291 (erscheint Mitte 2002)

Empower peopleEmpower people

through great through great softwaresoftware

any time, any place,any time, any place,

and on any deviceand on any device