Вы находитесь на странице: 1из 6

ADO.

Net
ActiveX Data Object .Net (ADO.Net)
ADO.Net
API d’accès (local ou distant)
à une source de données : SGBD, tableur, fichier, messagerie, …

Fonctionne selon un principe client/serveur (local ou distant)


• client = le programme (C#, VB, C++, …)
Lionel Seinturier • serveur = la source de données

INRIA Futurs Lille – Projet JACQUARD Principe


Université Pierre & Marie Curie • le programme ouvre une connexion
• il envoie des requêtes SQL
Lionel.Seinturier@lifl.fr • il récupère les résultats
• ...
• il ferme la connexion
30/8/04

ADO.Net 1 Lionel Seinturier ADO.Net 2 Lionel Seinturier

ADO.Net ADO.Net
ActiveX Data Object .Net (ADO.Net) Historique
ODBC Accès SGBD
• API d'interaction avec un SGBD
• nombreuses utilisations évolutions
- sauvegarde de données de manière sûre VB RDO DAO C++
- exploration du contenu d'un SGBD
unification
- client/serveur 3 tiers
OLE-DB ts langages – API COM

présentation traitement donnée simplification


(+ haut niveau)

ADO
ADO.Net
framework .Net
client serveur d'applications SGBD ADO.Net

ADO.Net 3 Lionel Seinturier ADO.Net 4 Lionel Seinturier


ADO.Net ADO.Net
Fournisseur (provider) ADO.Net Connection string ADO.Net

Implémentation de l’API pour un type de sources de données Identifie la source de données à laquelle on se connecte
Principaux providers • chaîne de caractères
• liste de couples propriété=valeur
• SQL Server (>= 7.0) System.Data.SqlClient.SqlConnection
• format dépend du provider
• OLE-DB (SQL Server < 7.0, …) System.Data.OleDb.OleDbConnection
• ODBC (Excel, Access, …) System.Data.Odbc.OdbcConnection
Exemple
• MySQL http://sourceforge.net/projects/mysqlnet/
•… • ODBC
Fournisseur "Driver={SQL Server};Server=localhost;Database=mydb;Uid=login;Pwd=passwd"
Chaque provider = une classe • OLE-DB
OLE-DB “Provider=sqloledb;Data Source=…;Database=…;User Id=…;Password=…”
•…
ODBC
voir http://geekswithblogs.net/brcraju/archive/2004/02/03/1689.aspx

ADO.Net 5 Lionel Seinturier ADO.Net 6 Lionel Seinturier

ADO.Net ADO.Net
Utilisation de ADO.Net Utilisation de ADO.Net (suite)

L'ensemble de l'API ADO.Net est définie dans System.Data 3. Récupération du résultat

1. Ouverture d'une connexion avec la base comptes reader.Read() retourne vrai tant qu'il reste des enregistrements dans le résultat
OdbcConnection cx = et positionne le curseur sur l'enregistrement suivant
new OdbcConnection("Driver={SQL Server};Server=localhost;Database=pubs;");
cx.Open(); reader.GetString(int column) (ex. : reader.GetString(0) )
retourne la valeur de la colonne 0 de type String de l’enregistrement courant
2. Envoi d'une requête SELECT
OdbcCommand cmd = new OdbcCommand("SELECT * FROM ages"); GetInt32, GetBoolean, GetByte, GetDouble, GetFloat
OdbcDataReader reader = cmd.ExecuteReader(); idem pour des colonnes de type int, boolean, byte, double ou float

Envoi d'une requête CREATE, INSERT ou UPDATE while( reader.Read() ) {


OdbcCommand cmd = new OdbcCommand("INSERT INTO ages VALUES ('toto',12)"); String nom = reader.GetString(0);
cmd.ExecuteNonQuery(); int age = reader.GetInt32(1);
Console.WriteLine( nom + " a " + age + " ans" );
}

ADO.Net 7 Lionel Seinturier ADO.Net 8 Lionel Seinturier


ADO.Net ADO.Net
Utilisation de ADO.Net (code complet) Types de requêtes SQL
using System.Data; • "normale"
using System.Data.Odbc;
- interprétée à chaque exécution
public class TestADONet {
• précompilée
public static void Main( String[] args ) {
- paramétrable
OdbcConnection cx = new OdbcConnection( - préparée pour être exécutée plusieurs fois
"Driver={SQL Server};Server=localhost;Database=pubs;" );
cx.Open(); - gérée par le programme
OdbcCommand cmd = new OdbcCommand("SELECT * FROM ages",cx); • procédure stockée
OdbcDataReader reader = cmd.ExecuteReader(); - paramétrable
while (reader.Read()) { - écrite dans le langage interne du SGBD (ex SQL Server Transac-SQL)
string nom = reader.GetString(0); - gérée par le SGBD
int age = reader.GetInt32(1);
Console.WriteLine( nom + " a " + age + " ans" ); + masque schéma base - langage propriétaire (- évolution)
} + meilleures perf - risque de mélange
cx.Close(); + validées par rapport schéma base logiques traitement/donnée
} }

ADO.Net 9 Lionel Seinturier ADO.Net 10 Lionel Seinturier

ADO.Net ADO.Net
Requêtes SQL précompilées Procédures stockées

1. Possibilité de définition de 1 ou +sieurs paramètres ! caractères ? Exemple de procédure stockée Transact-SQL (SQL Server)
OdbcCommand cmd = new OdbcCommand CREATE PROCEDURE [pubs].[GetRange]
("SELECT * FROM ages WHERE nom=? AND age>?",cx); @age int
AS
SELECT nom FROM ages WHERE age < @age
2. Valeurs des paramètres ajoutés à la commande GO
cmd.Parameters.Add(new OdbcParameter("","Bob"),cx);
cmd.Parameters.Add(new OdbcParameter("",Convert.ToInt32(5)),cx); Le code d’appel de la procédure
• new OdbcParameter( string name, object value ) OdbcCommand cmd = new OdbcCommand("GetRange",cx);
• paramètres ajoutés dans l'ordre de leur définition dans la requête cmd.CommandType = CommandType.StoredProcedure;
• name non significatif dans ce contexte (voir procédure stockée) cmd.Parameters.Add( new OdbcParameter("age",Convert.ToInt32(5) );
OdbcDataReader reader = cmd.ExecuteReader();
3. Exécution de la requête ...

OdbcDataReader reader = cmd.ExecuteReader();


...

ADO.Net 11 Lionel Seinturier ADO.Net 12 Lionel Seinturier


ADO.Net ADO.Net
Transactions Transactions

Groupes de requêtes devant être exécutés de façon indivisible Exemple

CREATE TABLE comptes (nom VARCHAR(30) PRIMARY KEY, solde FLOAT CHECK(solde>=0) );
La transaction doit être
OdbcCommand cmd1, cmd2;
- validée (commit) ! les résultats ne sont visibles qu'à partir de ce moment cmd1 = new OdbcCommand("UPDATE comptes SET solde=solde+montant WHERE nom='Paul'",cx);
cmd2 = new OdbcCommand("UPDATE comptes SET solde=solde-montant WHERE nom='Bob'",cx);
- ou annulée (rollback)
OdbcTransaction trans = cx.BeginTransaction();
OdbcCommand cmd1 = new OdbcCommand("INSERT INTO ages VALUES ('Pierre',12)",cx);
OdbcCommand cmd2 = new OdbcCommand("UPDATE ages SET age=15 WHERE nom='Joe'",cx); try {
cmd1.Transaction = trans;
OdbcTransaction trans = cx.BeginTransaction(); cmd2.Transaction = trans;
cmd1.Transaction = trans; cmd1.ExecuteNonQuery();
cmd2.Transaction = trans; cmd2.ExecuteNonQuery();
trans.Commit();
cmd1.ExecuteNonQuery(); déclaration du début de la transaction
cmd2.ExecuteNonQuery(); }
catch( Exception e ) {
trans.Commit(); validation de la transaction trans.Rollback();
}

ADO.Net 13 Lionel Seinturier ADO.Net 14 Lionel Seinturier

ADO.Net ADO.Net
Accès aux données en mode déconnecté Accès aux données en mode déconnecté

• par défaut c/s connecté vers SGBD • datasets : représentation mémoire des données d'un SGBD
+ 1 seule copie des données (SGBD) SELECT …
+ mises à jour simples adapter.Update(dataset)
rés
eau Data
connecté vs non connecté DataSet SGBD
Adapter
n messages petite taille SELECT …
vs 1 message grande taille
rés adapter.Fill(dataset)
eau

DataAdapter : gère liaison mémoire (DataSet) – SGBD


Déconnecté
! contient les requêtes SQL (select, update, insert) associées aux données
• pouvoir consulter/modifier les données off line
• économiser les ressources réseaux (connexions moins longues)
• travailler sur des données en mémoire plutôt que directement sur un SGBD

ADO.Net 15 Lionel Seinturier ADO.Net 16 Lionel Seinturier


ADO.Net ADO.Net
DataSet Exemple d'utilisation d'un DataSet

Un DataSet contient OdbcConnection cx = new OdbcConnection(


"Driver={SQL Server};Server=localhost;Database=pubs;" );
• des DataTable données sous forme de table cx.Open();
- des DataColumn OdbcDataAdapter adapter = new OdbcDataAdapter();
- nom, type, propriétés (autoincrement, unique, readonly, maxlength, …), … adapter.SelectCommand = new OdbcCommand("SELECT * FROM comptes",cx);
- des DataRow OdbcCommandBuilder builder = new OdbcCommandBuilder(adapter);
- valeurs DataSet dataset = new DataSet();
- des DataConstraint adapter.Fill(dataset);
• des DataRelation relation entre 2 DataTable cx.Close();
• une DefaultView
for( int i=0 ; i<dataset.Tables.Count ; i++ ) {
DataTable table = dataset.Tables[i];
Un DataSet peut être DataColumnCollection columns = table.Columns;
for( int j=0 ; j<table.Rows.Count ; j++ ) {
• consulté DataRow row = table.Rows[j];
• modifié (valeurs, lignes) ! mise à jour BD lors de Update() Console.WriteLine("Row "+j+": "+row["nom"]+" "+row["solde"]);
• sauvegardé/chargé en XML } }

ADO.Net 17 Lionel Seinturier ADO.Net 18 Lionel Seinturier

ADO.Net ADO.Net
Mise à jour d'un DataSet DataView

Modification d'une valeur Vue (pas de copie des données) sur une Datatable
table.Rows[0][0] = "Bill"; • séléction
adapter.Update(dataset);
• tri
Ajout d'une ligne
Mise à jour données dans la vue = maj des données dans la DataTable
DataRow myDataRow = table.NewRow();
myDataRow["nom"] = "John"; DataView view = new DataView(table);
myDataRow["solde"] = 123; view.RowFilter = "nom='Bob'"; // sélection de(s) Bob
table.Rows.Add(myDataRow); for( int i=0 ; i < view.Count ; i++ ) {
adapter.Update(dataset); view.Delete(i); // suppression aussi dans la DataTable
}
view.Sort = "nom, age DESC"; // d'abord pas nom puis par age décroissant

Expression de sélection "à la SQL"


- opérateur LIKE nom LIKE '*ob*'
- fonctions sum, avg, count, min, max
ADO.Net 19 Lionel Seinturier ADO.Net 20 Lionel Seinturier
ADO.Net ADO.Net
Utilisation des DataSet avec les DataGrid Trou de sécurité (bien connu)

DataGrid Attaque "SQL injection" à partir de formulaires Web


composants CREATE TABLE notes ( netudiant text, note float );
WinForm et WebForm
Formulaire traité ASP (idem PHP, JSP, …)
d'édition de
données tabulaires String num = ...
String requete =
"SELECT * FROM notes WHERE netudiant='"+num+"'";
datagrid.DataSource =
OdbcCommand cmd = new OdbcCommand(requete,cx);
dataset.Tables[0];
datagrid.DataBind();
Saisie '; SELECT * FROM notes WHERE ''='

requete =
SELECT * FROM notes WHERE
Data netudiant=''; SELECT * FROM notes WHERE ''=''
DataGrid DataSet
Adapter SGBD ! toutes les notes !!

ADO.Net 21 Lionel Seinturier ADO.Net 22 Lionel Seinturier

ADO.Net ADO.Net
Comparaison ADO.Net - JDBC Comparaison ADO.Net - JDBC

ADO.Net JDBC ADO.Net JDBC


c/s oui oui ≠ niv. isolation oui oui
accès provider driver méta-données oui oui
désignation Driver=… jdbc:mysql://… batch non oui
initialisation new … Class.forName("…") pool de cx oui (provider) oui (JNDI)
connexion Open() DriverManager.getConnection
commande …Command Statement/PreparedStatement/CallableState
curseur résultat …DataReader ResultSet
curs. multi-dir non oui
curs. maj non oui
deconnecté DataSet RowSet (JDBC 3.0)
transaction cx.BeginTransaction() cx.setAutoCommit(false)
trans.Commit() cx.commit()
trans.Rollback() cx.rollback()
≠ niv. isolation oui oui
ADO.Net 23 Lionel Seinturier ADO.Net 24 Lionel Seinturier