Etablir une connexion.................................................................................................................... 13 3.1 3.2 3.3 Les chanes de connexions .................................................................................................... 13 Les pools de connexions ........................................................................................................ 16 Dconnexion .......................................................................................................................... 17
Mode connect ............................................................................................................................. 18 4.1 4.2 4.3 4.4 4.5 4.6 4.7 4.8 4.9 Les commandes ..................................................................................................................... 18 Utiliser des commandes ........................................................................................................ 20 Les paramtres de commandes SQL ..................................................................................... 25 Les types de paramtres ....................................................................................................... 25 Crer un paramtre ............................................................................................................... 25 Les BLOBs............................................................................................................................... 28 Le DataReader ....................................................................................................................... 28 Copier un grand nombre de donnes ................................................................................... 28 Les transactions ..................................................................................................................... 29 Niveau disolations des transactions ............................................................................. 30 Les transactions Distribues .......................................................................................... 31
4.9.1 4.9.2 5
Mode dconnect ......................................................................................................................... 32 5.1 5.2 Le DataSet ............................................................................................................................. 32 Configurer un DataSet ........................................................................................................... 33 Crer un DataSet ........................................................................................................... 33 Ajouter des DataTable................................................................................................... 33 Le DataRelation ............................................................................................................. 34
14/09/08
Configurer une DataTable ..................................................................................................... 36 Crer des colonnes contenant des expressions ............................................................ 36 Lincrmentation dans une DataTable .......................................................................... 36 Les contraintes dans une DataTable ............................................................................. 37
Le DataAdapter ..................................................................................................................... 38 Crer un DataAdapter ................................................................................................... 38 Crer des commandes pour un DataAdapter ............................................................... 38 Le MissingMappingAction ............................................................................................. 39 Le MissingSchemaAction ............................................................................................... 39
Grer une DataTable ............................................................................................................. 40 Ajouter des donnes ..................................................................................................... 40 Grer des donnes ........................................................................................................ 40 Les vnements dune DataTable ................................................................................. 41
Exemples................................................................................................................................ 43 Remplissage automatique / Lecture de donnes .......................................................... 43 Remplissage manuel du DataSet ................................................................................... 45
5.7.1 5.7.2 6
Conclusion ..................................................................................................................................... 47
14/09/08
1 Introduction
Ce chapitre porte sur la gestion de base de donnes grce lADO.NET. LADO.NET permet de reli une application une base de donnes. La nouveaut de lADO.NET par rapport son anctre lADO est la gestion de donnes dans une application dans un environnement dconnect. Ce mode, par rapport au mode connect classique, possde plusieurs avantages et inconvnients. Ces deux modes sont utilisables avec les fournisseurs de base de donnes qui seront cits plus loin dans le chapitre. Bon cours .NET Lquipe ADO.NET.
14/09/08
14/09/08
Chaque fournisseur est reli une base de donnes propre, c'est--dire quil est compatible lAPI de sa base de donnes. Cependant, les bases de donnes peuvent implmenter plusieurs API (par exemple en installant certains pilotes comme ODBC pour lODBC) : Fournisseur SQL Server Description Les classes de ce fournisseur se trouvent dans lespace de nom System.Data.SqlClient, chaque nom de ces classes est prfix par Sql. SQL Server accs au serveur sans utiliser dautres couches logicielles le rendant plus performant. Les classes de ce fournisseur se trouvent dans lespace de nom System.Data.OleDb, chaque nom de ces classes est prfix par OleDb. Ce fournisseur exige linstallation de MDAC (Microsoft Data Access Components). Lavantage de ce fournisseur est quil peut dialoguer avec nimporte quelle base de donnes le temps que le pilote OLE DB est install dessus, mais par rapport SQL server, OLE DB utilise une couche logicielle nomme OLE DB ; il requiert donc plus de ressources diminuant par consquent les performances. Les classes de ce fournisseur se trouvent dans lespace de nom System.Data.Odbc, chaque nom de ces classes est prfix par Odbc. Tout comme lOLE DB, ODBC exige linstallation de MDAC. Il fonctionne avec le mme principe quOLE DB mais au lieu dutiliser une couche logicielle, il utilise le pilote ODBC. Les classes de ce fournisseur se trouvent dans lespace de nom System.Data.OracleClient, chaque nom de ces classes est prfix par Oracle. Il permet simplement de se connecter une source de donnes Oracle.
OLE DB
ODBC
Oracle
Remarque : SQL Server et Oracle sont tout deux des fournisseurs de donnes manags. C'est--dire quils sont optimiss pour certains types de bases de donnes.
14/09/08
Afin que laccs aux donnes soit sr, les fournisseurs de donnes doivent tre disponibles sur le poste de travail. La mthode GetFactoryClasses de la classe DbProviderFactories permet de donner les fournisseurs disponibles sur le poste de travail en question. Il faut, par contre, ajouter lespace de nom System.Data.Common. Par exemple :
VB
Imports System.Data; Imports System.Data.Common; //A rajouter Sub Main() Dim listeFournisseur As DataTable listeFournisseur = DbProviderFactories.GetFactoryClasses() For Each colonne As DataColumn In listeFournisseur.Columns Console.Write(colonne.ColumnName + vbTab) ' Affiche le nom des colonnes Next Console.WriteLine(vbNewLine + vbNewLine) For Each ligne As DataRow In listeFournisseur.Rows ' Affiche chaque ligne For Each colonne As DataColumn In listeFournisseur.Columns ' Affiche les cellules Console.Write(ligne.Item(colonne.ColumnName) + vbTab) Next Console.WriteLine(vbNewLine + vbNewLine) ' Retour la ligne Next End Sub
14/09/08
//C#
static void Main(string[] args) { DataTable listeFournisseur = DbProviderFactories.GetFactoryClasses(); foreach (DataColumn colonne in listeFournisseur.Columns) { Console.Write(colonne.ColumnName + "/t"); //Affiche le nom des colonnes } Console.WriteLine("/n/n"); foreach (DataRow ligne in listeFournisseur.Rows) //Affiche chaque ligne { foreach (DataColumn colonne in listeFournisseur.Columns) // Affiche les cellules { Console.Write(ligne[colonne.ColumnName] + "/t"); } Console.WriteLine("/n/n"); //Retour la ligne } Console.Read(); }
14/09/08
CommandBuilder
Connection
DataAdapter
DataReader
Transaction
Remarque : La classe Connection napparat pas dans le Framework 3.5. En effet, les classes des fournisseurs manags ont leur propre classe tel que SqlConnection.
14/09/08
IDataReader
IDataParameter
IDbCommand
IDbConnection
IDbDataAdapter
IDbTransaction
Ces interfaces ne montrent pas ltendue des possibilits que peut donner un fournisseur manag. En effet, les fournisseurs manags comprennent leurs propres classes permettant plus dactions ou en les amliorant.
14/09/08
10
Imports System.Data; Imports System.Data.Common; Imports System.Data.SqlClient; //A rajouter Sub Main() Dim requete, connexionString As String connexionString = "Data Source=.\SQLServeur;Initial Catalog=DotNetFrance;Integrated Security=true;" requete = "SELECT * FROM Employe" Dim connexion As IDbConnection = New SqlConnection(connexionString) Dim commande As IDbCommand = connexion.CreateCommand() commande.CommandText = requete commande.CommandType = CommandType.Text connexion.Open() Dim lire As IDataReader = commande.ExecuteReader() While (lire.Read()) Console.WriteLine("ID : {0} | Nom : {1} | Prenom : {2} | RoleNumero : {3}", lire.GetInt32(O), lire.GetString(1), lire("Prenom"), lire("Role")) End While connexion.Close() connexion.Dispose() Console.ReadLine() End Sub
14/09/08
11
//C#
static void Main(string[] args) { string requete, connexionString; connexionString = @"Data Source=.\SQLServeur;Initial Catalog=DotNetFrance;Integrated Security=true;"; requete = "SELECT * FROM Employe"; IDbConnection connexion = new SqlConnection(connexionString); IDbCommand commande = connexion.CreateCommand(); commande.CommandText = requete; commande.CommandType = CommandType.Text; connexion.Open(); IDataReader lire = commande.ExecuteReader(); while (lire.Read()) { Console.WriteLine("ID : {0} | Nom : {1} | Prenom : {2} | RoleNumero : {3}",lire.GetInt32(O),lire.GetString(1),lire["Prenom"],lire["Role"]); } connexion.Close(); connexion.Dispose(); Console.ReadLine(); }
12
jour. Ceci est possible grce au DataSet. Cest pourquoi, il existe deux types de fonctionnements : Le mode connect Le mode dconnect
Ci-aprs, la diffrence par avantages et inconvnients : Mode Connect Avantages Avec un mode connect, la connexion est permanente, par consquence les donnes sont toujours jour. De plus il est facile de voir quels sont les utilisateurs connects et sur quoi ils travaillent. Enfin, la gestion est simple, il y a connexion au dbut de lapplication puis dconnexion la fin. Lavantage est quil est possible de brancher un nombre important dutilisateurs sur le mme serveur. En effet, ils se connectent le moins souvent et durant la plus courte dure possible. De plus, avec cet environnement dconnect, lapplication gagne en performance par la disponibilit des ressources pour les connexions. Inconvnients Linconvnient se trouve surtout au niveau des ressources. En effet, tous les utilisateurs ont une connexion permanente avec le serveur. Mme si lutilisateur ny fait rien la connexion gaspille beaucoup de ressource entrainant aussi des problmes daccs au rseau.
Dconnect
Les donnes ne sont pas toujours jour, ce qui peut aussi entrainer des conflits lors des mises jour. Il faut aussi penser prvoir du code pour savoir ce que va faire lutilisateur en cas de conflits.
Il nexiste pas un mode meilleur que lautre, tout dpend de lutilisation que lon compte en faire.
14/09/08
13
SqlConnection connexion
La proprit ConnectionString permet dindiquer les paramtres de connexion. Cela se fait sous forme de chane de caractres, tel que par exemple :
VB
Voici les diffrents paramtres disponibles dans une ConnectionString : Paramtre Connect Timeout Description Indique le temps dattente de connexion en seconde. Ce laps de temps dpass, une exception est leve. Indique la dure de vie dune connexion dans un pool, la valeur 0 (zro) correspond linfini. Indique si la connexion a t rinitialise lors de son retour dans un pool. Indique le nom ou ladresse rseau du serveur. Indique le nom de la base de donnes o lapplication doit se connecter.
Connection LifeTime
Connection Reset
Data Source
Initial Catalog
14/09/08
14
Integrated Security
Indique sil faut un nom et un mot de passe. Si la valeur et sur False, un login et password seront demands. Indique le nombre maximum de connexion dans un pool. Par dfaut, le nombre maximum de connexions est 100. Indique le nombre minimum de connexion dans un pool. Indique si le nom et le mot de passe est visible par la connexion. Indique le mot de passe associ au compte SQL Server. Indique si une connexion peut tre sortie dun pool. Indique le nom du compte SQL Server.
Pwd
Pooling
User ID
Afin de vrifier ltat dune connexion, ADO.NET propose lnumration ConnectionState. Il possde diffrentes proprits : Proprit Broken Description Permet de savoir si la connexion est interrompue, cette connexion peux se fermer puis se rouvrir. Permet de savoir si lobjet connexion est ferm. Permet de savoir si lobjet connexion est en cours de connexion. Permet de savoir si une commande est en train de sexcuter. Permet de savoir si lobjet connexion est en train de rcuprer des donnes. Permet de savoir si lobjet connexion est ouvert.
Closed
Connecting
Executing
Fetching
Open
14/09/08
15
14/09/08
16
Voici les mots-cls de connexion de votre pool de connexion : Nom Par dfaut Description Quand une connexion tente de rejoindre le pool, si son temps de connexion dure plus de x secondes (x tant la valeur de la proprit), la connexion est stoppe. Dtermine si la connexion est remise zro lors de la cration dun ensemble de connexion. Si vous utilisez une connexion dans le cadre dune transaction, vous pouvez dfinir ce mot-cl sur True. Indique le nombre de secondes dune connexion avant quelle soit dtruite de lensemble. Indique le nombre maximum de connexions autorises dans un ensemble pour une chane de connexion spcifique. En dautres termes si votre connexion demande sans cesse de se connecter la base de donnes, vous pourriez avoir besoin daugmenter votre Max Pool Size (par dfaut 100 connexions autoriss).
Connection Lifetime
Connection Reset
True
Enlist
True
100
14/09/08
17
Dtermine le nombre minimum de connexions autoriss. Indique une valeur boolenne si la connexion est regroupe (True) ou si elle est ouverte chaque demande de connexion.
Pooling
True
En plus des mots-cls permettant de contrler le comportement des Connection Pool, il existe des mthodes qui ont des incidences sur un ensemble : Nom ClearAllPool Object SqlConnection et OracleConnection SqlConnection et OracleConnection Description Rinitialise toutes les Connection Pool. Rinitialise une Connection Pool spcifique. Spcifie au pool de connexions qu'il peut tre dtruit lorsque la dernire connexion qu'il contenait a t dtruite.
ClearPool
ReleaseObjectPool
OleDbConnection et Odbcconnection
3.3 Dconnexion
Pour couper la connexion entre lapplication et la base de donnes, il suffit dcrire :
VB
nomConnexion.Close()
//C#
nomConnexion.Close();
14/09/08
18
4 Mode connect
4.1 Les commandes
Contrairement une base de donnes, les requtes SQL et les procdures stockes sont excutes partir de commandes. Les commandes contiennent toutes les informations ncessaires leur excution et effectuent des oprations telles que crer, modifier ou encore supprimer des donnes dune base de donnes. Vous utilisez ainsi des commandes pour faire des excutions de requtes SQL qui renvoient les donnes ncessaires. Remarque : les requtes SQL et les procdures stockes sont deux choses diffrentes. En effet les procdures stockes sont des requtes SQL dj enregistres dans la mmoire cache du serveur. Chaque fournisseur de base de donnes possde leurs propres objets Command qui sont les suivantes : Nom SqlCommand OleDbCommand OdbcCommand OracleCommand Type de sources de donnes SQL Server OLE DB ODBC Oracle
Il existe plusieurs proprits et mthodes communes chaque fournisseur pour grer des commandes, voici les principales : Proprits Nom CommandText Description Permet de dfinir linstruction de requtes SQL ou de procdures stockes excuter. Li la proprit CommandType. Permet dindiquer le temps en secondes avant de mettre fin lexcution de la commande.
CommandTimeout
14/09/08
19
CommandType
Permet dindiquer ou de spcifier la manire dont la proprit CommandText doit tre excute. Permet dtablit une connexion. Cest la collection des paramtres de commandes. Lors de lexcution de requtes paramtres ou de procdures stockes, vous devez ajouter les paramtres objet dans la collection. Permet de dfinir la SqlTransaction dans laquelle la SqlCommand sexcute.
Connection Parameters
Transaction
Mthodes Nom Cancel Description Permet de tenter lannulation de lexcution dune commande. Permet dexcuter des requtes ou des procdures stockes qui ne retournent pas de valeurs. Permet dexcuter des commandes et les retourne sous forme de tableau de donnes (ou des lignes). Permet dexcuter les requtes ou les procdures stockes en retournant une valeur unique. Permet de retourner les donnes sous le format XML.
ExecuteNonQuery
ExecuteReader
ExecuteScalar
ExecuteXMLReader
Vous pouvez aussi manipuler des vnements. Voici les deux principaux : Evnements Disposed Description Permet dappeler la dernire mthode avant que lobjet ne soit dtruit.
14/09/08
20
Dim commande As SqlCommand = New SqlCommand() commande.Connection = connexion commande.CommandText = "SELECT * FROM Employe"
//C#
SqlCommand commande= new SqlCommand(); commande.Connection = connexion; commande.CommandText = "SELECT * FROM Employe";
La deuxime mthode est lutilisation dun constructeur surcharg, voici par exemple :
VB
La dernire mthode est dutiliser la mthode CreateCommand de l'objet de connexion comme dans lexemple ci-dessous :
VB
14/09/08
21
Le fonctionnement pour excuter une procdure stocke est quasiment identique lexcution dune requte SQL classique. Il faut que la proprit CommandText contienne le nom de la procdure, par contre la proprit CommandType doit prendre la valeur StoredProcedure au lieu de Text. Lavantage dune procdure stocke est une amlioration de la performance car la procdure se trouve prcompile dans le cache du serveur. Voici un exemple qui permet dafficher toutes les informations dun utilisateur de la table Employe :
VB
Dim connexion As SqlConnection = New SqlConnection("Data Source=.\SQLServeur;Initial Catalog=DotNetFrance;Integrated Security=True") Dim Command As SqlCommand = connexion.CreateCommand() connexion.Open() Dim id As String Dim requete As String = "RecupInformation" Command.CommandText = requete Command.CommandType = CommandType.StoredProcedure Console.WriteLine("Quel est l'id de la personne sur laquelle vous voulez les informations ?") id = Console.ReadLine() Dim paramIdToKnow As SqlParameter = New SqlParameter("@IdToKnow", id) Command.Parameters.Add(paramIdToKnow) Dim lecture As IDataReader = Command.ExecuteReader() While (lecture.Read()) Console.WriteLine("Id : {0} Nom : {1} Prenom : {2} Role : {3}", lecture("ID"), lecture.GetString(1), lecture.GetString(2), lecture.GetInt32(3)) End While connexion.Close() connexion.Dispose()
14/09/08
22
//C#
SqlConnection connexion = new SqlConnection(@"Data Source=.\SQLServeur;Initial Catalog=DotNetFrance;Integrated Security=True"); SqlCommand command = connexion.CreateCommand(); connexion.Open(); string id; string requete = "RecupInformation"; command.CommandText = requete; command.CommandType = CommandType.StoredProcedure; Console.WriteLine("Quel est l'id de la personne sur laquelle vous voulez les informations ?"); id = Console.ReadLine(); SqlParameter paramIdToKnow = new SqlParameter("@IdToKnow", id); command.Parameters.Add(paramIdToKnow); IDataReader lecture = command.ExecuteReader(); while (lecture.Read()) { Console.WriteLine("Id : {0} Nom : {1} Prenom : {2} Role : {3}", lecture["ID"], lecture.GetString(1), lecture.GetString(2), lecture.GetInt32(3)); } connexion.Close(); connexion.Dispose();
Afin dexcuter une instruction SQL qui renvoie plusieurs valeurs, on peut utiliser la mthode ExecuteReader; elle va retourner lobjet Datareader qui va permettre la lecture des donnes. Si linstruction SQL ne doit renvoyer quune valeur unique, on peut utiliser la mthode ExecuteScalar qui va la fois soccuper de lexcution et retourner la valeur.
14/09/08
23
Voici, par exemple, un code permettant dafficher la base de donnes Dot-Net France :
VB
Dim connexion As SqlConnection = New SqlConnection("Data Source=.\SQLServeur;Initial Catalog=DotNetFrance;Integrated Security=True") Dim Command As SqlCommand = connexion.CreateCommand() Dim requete As String = "SELECT e.ID 'ID', e.Nom, e.Prenom, r.Nom FROM Employe e, Role r WHERE(e.Role = r.ID) " Command.CommandText = requete connexion.Open() Dim lire As SqlDataReader = Command.ExecuteReader() Console.WriteLine("Lecture du DataReader" + vbNewLine + vbNewLine) ' Lit les informations de la base de donnes While (lire.Read()) Console.WriteLine("Id : {0} Nom : {1} Prenom : {2} Role : {3}", lire("ID"), lire.GetString(1), lire.GetString(2), lire.GetString(3)) End While ' Permet d'afficher connexion.Close() connexion.Dispose()
//C#
SqlConnection connexion = new SqlConnection(@"Data Source=.\SQLServeur;Initial Catalog=DotNetFrance;Integrated Security=True"); SqlCommand command = connexion.CreateCommand(); string requete = "SELECT e.ID 'ID', e.Nom, e.Prenom, r.Nom FROM Employe e, Role r WHERE(e.Role = r.ID) "; command.CommandText = requete; connexion.Open(); SqlDataReader lire = command.ExecuteReader(); // Lit les informations de la base de donnes Console.WriteLine("Lecture du DataReader \n\n"); while (lire.Read()) { Console.WriteLine("Id : {0} Nom : {1} Prenom : {2} Role : {3}", lire["ID"], lire.GetString(1), lire.GetString(2), lire.GetString(3)); } // Permet d'afficher connexion.Close(); connexion.Dispose();
14/09/08
24
Vous pouvez galement excuter des commandes qui vous renvoient les donnes au format XML. Pour cela vous devez rgler la proprit CommandText de votre instruction SQL au format XML puis faire appel la mthode ExecuteXMLReader qui retourne un objet XmlReader (dont la classe est stocke dans System.Xml). Lorsque vous configurez votre commande, vous pouvez utiliser le Query Designer afin de crer et de personnaliser vos requtes. Donc vous devez slectionner votre base de donnes dans le Server Explorer puis cliquer sur New Query. Vous ouvrez ainsi le Query Designer et pourrez alors non seulement crer votre requte mais en plus la personnaliser (tableau, affichage). Durant un change entre une application et une base de donnes, lapplication est bloque durant lattente de la rponse du serveur. Pour remdier ce problme, lADO.NET propose les commandes asynchrones. En effet, ces commandes permettent lapplication de faire autre chose en attendant la rponse du serveur. Voici les mthodes qui sont utilises lors dun processus asynchrone : Mthodes BeginExecuteNonQuery Description Commence la version asynchrone de la mthode ExecuteNonQuery. Commence la version asynchrone de la mthode ExecuteReader. Commence la version asynchrone de la mthode ExecuteXmlReader. Appeler cette mthode aprs lvnement StatementCompleted afin dachever lexcution de la commande. Appeler cette mthode aprs lvnement StatementCompleted afin de renvoyer le DataReader avec les donnes retournes par la commande. Appeler cette mthode aprs lvnement StatementCompleted afin de renvoyer le XmlReader avec les donnes retournes par la commande.
BeginExecuteReader
BeginExecuteXmlReader
EndExecuteNonQuery
EndExecuteReader
EndExecuteXmlReader
14/09/08
25
14/09/08
26
La classe SqlParameter permet de crer des objets de type Sqlparameter contenant : le nom, la valeur et la direction dutilisation du paramtre. Voici un exemple permettant dajouter un utilisateur dans la base de donnes DotNetFrance :
VB
Dim connexion As SqlConnection = New SqlConnection("Data Source=.\SQLServeur;Initial Catalog=DotNetFrance;Integrated Security=True") Dim Command As SqlCommand = connexion.CreateCommand() Dim nom, prenom, requete, role As String Console.WriteLine("Entrez les donnes suivantes :" + vbNewLine) Ecrit directement dans la console Console.WriteLine("Nom : ") nom = Console.ReadLine() Permet de lire la valeur donne Console.WriteLine(vbNewLine + "Prenom : ") prenom = Console.ReadLine() Console.WriteLine(vbNewLine + "Role (0 Stagiaire | 1 Manager) : ") role = Console.ReadLine() requete = "INSERT INTO Employe VALUES(@nom, '" + prenom + "'," + role + ")" Dim param As SqlParameter = New SqlParameter("@nom", nom) Permet de paramtrer "nom" Command.Parameters.Add(param) Ajoute le paramtre param la collection Parameters Command.CommandText = requete connexion.Open() Dim nbrEnregistrementAffecte As String = Command.ExecuteNonQuery().ToString() Console.WriteLine(vbNewLine + nom + " " + prenom + " " + role + " a ete ajoute.") Console.WriteLine("Il y a " + nbrEnregistrementAffecte + " enregistrement(s) affecte par la requete")
14/09/08
27
//C#
SqlConnection connexion = new SqlConnection(@"Data Source=.\SQLServeur;Initial Catalog=DotNetFrance;Integrated Security=True"); SqlCommand command = connexion.CreateCommand(); string nom, prenom, requete; int role; Console.WriteLine("Entrez les donnes suivantes :\n"); // Ecrit directement dans la console Console.WriteLine("Nom : "); nom = Console.ReadLine(); // Permet de lire la valeur donne Console.WriteLine("\nPrenom : "); prenom = Console.ReadLine(); Console.WriteLine("\nRole (0 Stagiaire | 1 Manager) : "); role = int.Parse(Console.ReadLine()); requete = "INSERT INTO Employe VALUES(@nom, '" + prenom + "'," + role + ")"; SqlParameter param = new SqlParameter("@nom", nom); // Permet de paramtrer "nom" command.Parameters.Add(param); // Ajoute le paramtre param la collection Parameters command.CommandText = requete; connexion.Open(); int nbrEnregistrementAffecte = command.ExecuteNonQuery(); Console.WriteLine("\n" + nom + " " + prenom + " " + role + " a ete ajoute."); Console.WriteLine("Il y a " + nbrEnregistrementAffecte + " enregistrement(s) affecte par la requete");
Remarque : Vous pouvez aussi ajouter des paramtres vos Command Object en saisissant la mthode GetCostCommand.
14/09/08
28
4.7 Le DataReader
Le DataReader permet un accs en lecture seule des enregistrements, c'est--dire quil est impossible de revenir en arrire sur les enregistrements lus. Il na t cr que pour la lecture pure et simple de donnes. Le DataReader doit toujours tre associ une connexion active, c'est--dire quil ne peut pas se dconnecter, effectuer quelque chose puis se reconnecter pour une mise jour. Il existe plusieurs Datareader suivant le fournisseur utilis, par exemple nous avons SqlDataReader ou encore OracleDataReader. Le DataReader comprend plusieurs mthodes : GetBytes, GetChars ou GetString. GetString servent pour les donnes caractres ; GetBytes et GetChars permettent de retourner une valeur de type long, qui reprsente le nombre de caractres ou doctets retourns.
14/09/08
29
Cration dune transaction Dim transaction As New SqlTransaction Dfinit la transaction votre connexion Transaction = VotreConnexion.BeginTransaction()
//C#
Cration dune transaction SqlTransaction transaction Dfinit la transaction votre connexion transaction = VotreConnexion.BeginTransaction() ;
De plus les transactions reposent sur le principe de quatre caractristiques appel ACID qui apporte plus de clart sur la dfinition dune transaction : Atomicit, qui signifie que la mise jour de la base de donnes doit tre totale ou nulle, cest le principe du tout ou rien. Cohrence, qui indique que les modifications apportes doivent tre valides.
Isolation, qui dfinit que les transactions lances au mme moment ne doivent pas sinterfrer entre elles. Durabilit, qui assure que toutes les transactions sont lances de manire dfinitive.
Les transactions sont manages au niveau de la connexion. Par consquent nous pourrons commencer une transaction en ouvrant une connexion avec une base de donnes pour ensuite commencer les transactions en appelant la mthode BeginTransaction issues dune instance de la classe SqlTransaction. Puis vous devez dfinir quelle commande ncessite une transaction. Enfin la fin du traitement des donnes vous avez la possibilit
14/09/08
30
soit de valider vos transactions grce la mthode Commit soit de les annuler grce la mthode Rollback.
Les niveaux disolation vous permettent de grer les problmes dintgrit des donnes ainsi que des accs simultans celles-ci par le biais des transactions. Vous trouverez ci-dessous la liste des proprits IsolationLevel associs lobjet Transaction : Nom Chaos Description Les modifications en attente de transactions trs isols ne peuvent tre crases. Les verrouillages partags sont maintenus pendant que les donnes sont en lecture pour viter tout dfaut, mais les donnes sont modifiables durant la transaction, entrainant une lecture non rptable ou des donnes fantme. Il ny a pas de verrouillage entrainant la possibilit de tout dfaut de lecture. Toutes les donnes utilises dans une requte sont verrouilles. Par consquence les lectures ne sont pas rptables mais des donnes fantme peuvent exister et dautres utilisateurs ne peuvent mettre jour les donnes. Les verrouillages sont placs sur toutes les donnes qui sont utilises dans une requte, ce qui empche dautres utilisateurs de mettre jour les donnes. Rduit le blocage par le stockage de donnes quune seul application peut lire pendant quune autre est train de les modifier. Cela indique que dune seule transaction vous ne pouvez voir les modifications faites dans dautres transactions. Aucun niveau ne peut tre dtermin. Ainsi si le niveau disolation est dfinit sur celui-ci alors la transaction excute selon le niveau disolation par dfaut du sous-jacent du type de base de donnes.
ReadCommitted
ReadUncommitted
RepeatableRead
Serializable
Snapshot
Unspecified
14/09/08
31
En plus de crer des nouvelles transactions et de dfinir des niveaux disolation de celles-ci, vous pouvez configurez votre connexion pour lengager dans une transaction distribue. Une transaction distribue est une transaction qui stend sur de nombreuses ressources, telles que de multiples bases de donnes SQL. Exemple de mise en place dune transaction distribue :
VB
VotreConnexion.EnlistTransaction(activeTransaction)
//C#
VotreConnexion.EnlistTransaction(activeTransaction) ;
14/09/08
32
5 Mode dconnect
5.1 Le DataSet
Le DataSet est stock dans lespace de nom System.Data. Cest un cache de donnes en mmoire, c'est--dire quil permet de stocker temporairement des donnes utilises dans votre application. Le DataSet contient la collection dobjets DataTable qui peuvent tre lis avec les objets DataRelation. Dans le cas du mode dconnect, cet objet va nous permettre d'importer la partie dsire de la base de donnes (fonction de la requte de slection) en local. Ainsi grce des objets ncessaire la connexion classique (commande select, connections string...) et un DataAdapter, nous pourrons relier ("Binder") un DataSet sur une base de donne (en lecture et en criture grce a une mthode de mise a jour de la base de donne).
Grce au mot cl foreach, on peut parcourir des DataSet ou les requter en Linq. La cration dun DataSet peut se faire via plusieurs mthodes : On peut le crer par programmation en crant des objets DataTable, DataRelation (facultatif). Il suffit ensuite de remplir la ou les base(s) de donnes. Vous pouvez aussi utiliser le Designer DataSet et lassistant de configuration de Data Source afin de crer un objet DataSet. Pour cela vous devez mettre en place le processus de connexion des donnes en slectionnant une base de donnes disponible, qui permettra de mettre en place un DataSet typ. Ainsi cela gnra le code ncessaire pour cette cration. Vous pouvez aussi glisser directement un DataSet depuis la Toolbox sur votre Form (cas pour le WinForm)
14/09/08
33
Il existe deux types de DataSet : Typed DataSet : Cela permet de crer une instance dune classe DataSet dj type dans votre projet. Untyped Dataset : Cela permet de crer une instance dune classe DataSet non-typ de la classe System.Data.DataSet. Voici les lments dun DataSet : Objet DataTable Description Correspond une table. Contient une collection de DataColumn et de DataRow. Reprsente une colonne de la table. Correspond un enregistrement de la table.
DataColumn DataRow
Pour crer un DataSet, il faut en premier lieu les instancier (vous pouvez aussi dfinir leur nom) :
VB
5.2.2 Ajouter des DataTable Aprs avoir cr votre DataSet, vous pouvez lui ajouter des DataTable comme ceci :
VB
Dim Employe As New DataTable Dim Role As New DataTable DotNetFranceDataSet.Tables.Add(Employe) DotNetFranceDataSet.Tables.Add(Role)
14/09/08
34
//C#
DataTable Employe = new DataTable(); DataTable Role = new DataTable(); DotNetFranceDataSet.Tables.Add(Employe); DotNetFranceDataSet.Tables.Add(Role);
5.2.3 Le DataRelation
Lobjet DataRelation reprsente le lien entre plusieurs tables. Dans un DataSet, il permet la relation entre les colonnes de plusieurs DataTable. Par exemple, nous pouvons lier les colonnes ID et Role de nos tables Employe et Role :
VB
//C#
Ensuite, grce cette relation, vous pouvez naviguer entre les colonnes de vos tables. Le DataRow propose deux mthodes : le GetParentRow et le GetChildRows : Mthode GetParentRows Description Permet dobtenir les lignes parentes dun DataRow attach un DataRelation. Permet dobtenir les lignes enfants dun DataRow attach un DataRelation.
GetChildRows
Par exemple, nous pouvons afficher les ID de notre prcdente relation EmployeRole :
VB
//C#
14/09/08
35
La mthode Merge permet de fusionner deux DataSet entre eux. On prend un DataSet source quon fusionne avec un DataSet cibl. Pour des tables identiques, ce sont les donnes du DataSet source qui remplaceront les donnes du DataSet cibl. Lorsquil sagit de deux DataSet diffrents, vous pouvez paramtrer la mthode Merge avec la proprit MissingSchemaAction. Voici les diffrentes valeurs de ce paramtre : Valeur Add Description Permet dajouter les objets contenus dans le DataSet source dans le DataSet cibl. Permet dajouter les objets contenus dans le DataSet source dans le DataSet cibl avec les cls primaires. Une exception sera leve si le mappage dune colonne dans les DataSet source et cibl est manquante. Toutes les colonnes du DataSet source supplmentaire sont ignores.
AddWithKey
Error
Ignore
Vous pouvez par exemple vouloir modifier pour une srie de test un DataSet. Pour cela, il est trs simple de copier un DataSet. Il suffit dutiliser la mthode Copy :
VB
//C#
14/09/08
36
Dans une base de donnes, vous pouvez avoir besoin de crer des colonnes contenant des expressions. Ceci fonctionne un peu comme avec un tableau Microsoft Excel, vous pouvez crer des expressions dans une colonne qui permet de calculer une somme, une multiplication ou autre plus complexe. Il existe pour cela lobjet Expression :
VB
//C#
Remarque : Si vous grez des nombres virgules, changez le paramtre Decimal en Double.
5.3.2 Lincrmentation dans une DataTable
Lauto-incrmentation est le fait dincrmenter (augmenter) un nombre. On peut lincrmenter avec un nombre positif ou un nombre ngatif. Lincrmentation se fait sur une colonne. Pour incrmenter, il faut mettre True la proprit AutoIncrement. La proprit AutoIncrementSeed dfinit le nombre de dpart et AutoIncrementStep dfini le pas de lincrmentation (cest celui qui peut tre positif ou ngatif).
14/09/08
37
Une DataTable, l'image des contraintes dans les bases de donnes relationnelles, peut galement avoir des contraintes appliques certaines de ses colonnes. Rappel : En SQL, une cl primaire permet didentifier de manire unique chaque ligne dune table. Les champs associs une cl primaire ont une valeur unique dans une table. Une cl trangre permet de faire une rfrence vers une autre colonne de la table ou vers une autre table, possdant obligatoirement une cl primaire. Par exemple cette base de donnes :
Il existe les mmes deux types de cls : les cls trangres et les cls primaires. Les cls primaires : Pour installer une cl primaire une valeur unique, il suffit de crer linstance de la classe UniqueConstraint et dassigner la colonne avec la valeur unique au constructeur. Les cls trangres : Afin dajouter une cl une ou plusieurs colonnes voir plusieurs tables parents aux colonnes enfants il faut faire linstance de la classe ForeignKeyConstraint. Cette classe possde les proprits DeleteRule et UpdateRule qui permet de dfinir le comportement. Il en existe quatre valeurs : Valeur Cascade Description Les modifications se font sur toutes les lignes lies par la cl. Les modifications ne se font pas sur les lignes lies par la cl. La valeur par dfaut est donne dans les lignes lies. La valeur est modifie par DBNull.
None
SetDefault SetNull
14/09/08
38
5.4 Le DataAdapter
Lobjet DataAdapter permet de relier un DataSet une base de donnes. En revanche le DataAdapter change suivant le fournisseur, c'est--dire, par exemple, pour une base de donnes SQL, ce sera SqlDataAdapter. Cest grce cela que votre application pourra communiquer avec la base de donnes et par exemple mettre jour celle-ci.
Pour crer un DataAdapter, il faut tout dabord instancier celui correspondant votre fournisseur. Il a besoin dune commande pour fonctionner. Par exemple :
VB
//C#
Il est possible dajouter plusieurs commandes un DataAdapter. Pour cela, il suffit de crer votre commande puis de lajouter votre DataAdapter. Par exemple, voici une commande associe un DataAdapter permettant de modifier le prnom de la table Employe :
VB
Dim ModifierNom As New SqlCommand("UPDATE Employe SET Prenom = 'Jeremie' WHERE Prenom='Jeremy'") DotNetFranceAdapter.ModifierNom = ModifierNom
//C#
SqlCommand ModifierNom = new SqlCommand("UPDATE Employe SET Prenom = 'Jeremie' WHERE Prenom='Jeremy'"); DotNetFranceAdapter.ModifierNom = ModifierNom;
14/09/08
39
5.4.3 Le MissingMappingAction
Cette proprit permet de rgler certains conflits entre un DataSet et une base de donnes. En effet des conflits peuvent arriver si on tente par exemple de remplir un DataSet (avec une base de donnes) dans lequel il manque soit des colonnes ou des tables.
Lnumration MissingMappingAction possde ces valeurs possibles : Valeur Error Description Permet de lever lexception InvalidOperationException si une colonne est manquante. Permet de retourner une valeur NULL si une table ou une colonne est manquante. Permet de crer la colonne et/ou la table manquante.
Ignore
Passthrough
5.4.4 Le MissingSchemaAction
Cette proprit permet aussi de rgler les conflits entre un DataSet et une base de donnes. Il permet de spcifier o et comment ajouter des donnes dans des DataTable et DataColumn manquante. Voici les valeurs de lnumration MissingMappingAction : Valeur Add AddWithKey Error Description Permet de crer la colonne et/ou la table manquante. Permet dajouter les cls ncessaires aux colonnes. Permet de lever lexception InvalidOperationException si une colonne est manquante. Permet dignorer les colonnes en trop.
Ignore
14/09/08
40
Afin dajouter des donnes dans une DataTable, il faut tout dabord crer un nouveau DataRow. Aprs avoir cr votre ligne, vous pouvez y ajouter vos valeurs. Par exemple, nous pouvons ajouter un nouvel utilisateur notre base de donnes avec un ID, Nom, Prenom et le role :
VB
Vous pouvez aussi diter ou supprimer des donnes dans votre DataTable comme ceci : Langage C# VB Modifier MaLigne ["ID"] = "Numero" ; MaLigne ("ID") = "Numero" Supprimer MaLigne.Delete() ; MaLigne.Delete
Le RowState vous permet de grer le statut dune ligne. Par dfaut, il se trouve sur Unchanged. Voici les valeurs possibles de cette numration : Valeur Added Description Permet la ligne de sajouter dans la collection DataRowCollection. Permet de supprimer la ligne en utilisant la mthode Delete de DataRow. Permet de crer la ligne sans quelle nappartienne la collection DataRowCollection.
Deleted
Detached
14/09/08
41
Modified Unchanged
La DataTable possde ses propres vnements : Evnement ColumnChanged Description Se dclenche lorsquune valeur a t change dans un DataRow dune DataColumn. Se dclenche lorsquune valeur est en train dtre change dans un DataRow dune DataColumn. Est appele lorsque la mthode Dispose est appele. Se dclenche aprs que la DataTable soit initialise. Se dclenche lorsquun DataRow a bien t modifi. Se dclenche lorsquun DataRow est en modification. Se dclenche lorsque quune ligne a t supprime. Se dclenche lorsque quune ligne est entrain dtre supprime. Se dclenche quand une DataTable a t vide. Se dclenche quand une DataTable se vide. Se dclenche lorsquun DataRow est ajout.
ColumnChanging
Disposed
Initialized
RowChanged
RowChanging
RowDeleted
RowDeleting
TableCleared
TableClearing TableNewRow
14/09/08
42
5.6 Le DataView
Un DataView permet davoir une vue dune DataTable. Cela permet aussi de pouvoir la trier, la modifier. La fonction principale de cet objet est de relier une base de donnes aux applications WinForm et WebForm.
5.6.1
Crer un DataView
Afin de crer un DataView, il suffit de crer linstance de celle-ci et dy placer le nom de la DataTable souhaite. Par exemple :
VB
La proprit Sort du DataView permet de le trier. On peut le trier de deux faons : ASC (croissant) et DESC (dcroissant). La faon croissante est par dfaut utilise par le DataView.
VB
DataRowView("Nom") = "Jeremie"
14/09/08
43
//C#
DataRowView("Nom") = "Jeremie";
Lvnement principal dun DataView est le ListChanged. Cet vnement se dclenche lorsque quil y a un changement dans une DataTable ou DataRelation reli ce DataView.
5.7 Exemples
5.7.1 Remplissage automatique / Lecture de donnes
VB
Dim requete, connexionString As String connexionString = "Data Source=.\SQLServeur;Initial Catalog=DotNetFrance;Integrated Security=true;" requete = "SELECT * FROM Employe" Dim ds As DataSet = New DataSet() Dim da As IDbDataAdapter = New SqlDataAdapter() Dim connexion As IDbConnection = New SqlConnection(connexionString) Dim commande As IDbCommand = connexion.CreateCommand() commande.CommandText = requete ' On choisit la commande qui sera excut par le DataAdapter et on rempli le DataSet da.SelectCommand = commande da.Fill(ds)
'Affichage du DataSet Console.WriteLine("Nom de la table : {0} | Il possde {1} enregistrement(s)" + vbNewLine + vbNewLine + vbNewLine, ds.Tables(0), ds.Tables("Table").Rows.Count) 'On affiche les informations que lon tire du DataSet
For Each colonne As DataColumn In ds.Tables(0).Columns 'Affichage des noms des colonnes Console.Write(colonne.ColumnName + vbTab) Next Console.WriteLine(vbNewLine + vbNewLine) For Each ligne As DataRow In ds.Tables(0).Rows 'Afichage des enregistrements
14/09/08
44
//C#
string requete, connexionString; connexionString = @"Data Source=.\SQLServeur;Initial Catalog=DotNetFrance;Integrated Security=true;"; requete = "SELECT * FROM Employe"; DataSet ds = new DataSet(); IDbDataAdapter da = new SqlDataAdapter(); IDbConnection connexion = new SqlConnection(connexionString); IDbCommand commande = connexion.CreateCommand(); commande.CommandText = requete; commande.CommandType = CommandType.Text; // On choisit la commande qui sera execut par le DataAdapter et on rempli le DataSet da.SelectCommand = commande; da.Fill(ds); //Affichage du DataSet Console.WriteLine("Nom de la table : {0} | Il possde {1} enregistrement(s) \n\n\n", ds.Tables[0],ds.Tables["Table"].Rows.Count); //On affiche les informations que lon tire du DataSet foreach (DataColumn colonne in ds.Tables[0].Columns) //Affichage des noms des colonnes { Console.Write(colonne.ColumnName + "\t"); } Console.WriteLine("\n\n"); foreach (DataRow ligne in ds.Tables[0].Rows) //Afichage des enregistrements { foreach (DataColumn colonne in ds.Tables[0].Columns) { Console.Write(ligne[colonne.ColumnName] + "\t"); } Console.WriteLine("\n"); } Console.ReadLine();
14/09/08
45
Module Module1 Sub Main() Dim ds As DataSet = New DataSet("Dotnet-France") Dim stagiaires As DataTable = New DataTable("Stagiaires") ' cette table contient trois champs renseigner pour chaque enregistrement stagiaires.Columns.Add("ID", GetType(Integer) ' l'id stagiaires.Columns.Add("Nom", GetType(String)) ' le nom stagiaires.Columns.Add("Description", GetType(String)) ' description ' mthode du dictionnaire Dim dnom As Dictionary(Of String, String)= New Dictionary(Of String, String)() dnom.Add("Cdric", "Stagiaire") dnom.Add("Christophe", " Stagiaire ") ' pour chaque paire d'lments nous allons ajouter des enregistrements For Each elem As KeyValuePair(Of String, String) In dnom stagiaires.Rows.Add(Class1.StagiaireID, elem.Key, elem.Value) Next ' des listes Dim nom() As String = {"Jrmy", "Cdric"} Dim desc As String() = {"Manager ", "Manager"} ' s'il y a beaucoup de champs pour des raisons de lisibilits il peut etre prfrable ' de ranger chaque liste dans un Dictionary<string,List<string>> For i = 0 To nom.Length - 1 Step 1 stagiaires.Rows.Add(Class1.StagiaireID, nom(i), desc(i)) Next ' et comme vous l'aurez compris :remplissage brut ' (s'il n'y a que trs peut d'entre peut etre une bonne solution) stagiaires.Rows.Add(Class1.StagiaireID, "Paul", "Stagiaire") stagiaires.Rows.Add(Class1.StagiaireID, "Quentin", "Stagiaire") ' on peut ranger notre table dans notre DataSet ds.Tables.Add(stagiaires) ' donc nous allons afficher pour prouver le fonctionnement ' les donnes dans un terminal For Each row As DataRow In ds.Tables("stagiaires").Rows For Each col As DataColumn In stagiaires.Columns Console.Write(row.Item(col.ColumnName).ToString() + vbTab) Next ' retour la ligne entre chaque enregistrement. Console.WriteLine() Next Console.ReadLine() End Sub Public Class Class1 ' on cre une valeur id avec acesseur pour l'auto incrementation Private Shared _stagiaireid As Int32 = 0 Public Shared ReadOnly Property StagiaireID() As Int32 Get _stagiaireid += 1 Return _stagiaireid End Get End Property End Class End Module
14/09/08
46
//C#
class MainClass { public static void afficheTable(DataSet ds, string tableName) { foreach (DataColumn col in ds.Tables[tableName].Columns) { Console.Write(col.ColumnName + "\t"); } Console.WriteLine(); foreach (DataRow row in ds.Tables[tableName].Rows) { foreach (DataColumn col in ds.Tables[tableName].Columns) { Console.Write(row[col.ColumnName].ToString() + "\t"); } Console.WriteLine(); } Console.WriteLine("\n"); } private static int _stagiaireid = 0; public static int StagiaireID { get { return _stagiaireid++; } } public static void Main(string[] args) { DataSet ds = new DataSet("dotnet-france"); DataTable stagiaires = new DataTable("stagiaires"); // cette table contient trois champs renseigner pour // chaque enregistrement l'id, le nom et la description stagiaires.Columns.Add("id", typeof(int)); stagiaires.Columns.Add("nom ", "text".GetType()); stagiaires.Columns.Add("description", typeof(string)); // Rangement dans une collection gnrique Dictionary<string, string> dnom = new Dictionary<string, string>(); dnom.Add("Cdric", "Stagiaire"); dnom.Add("Christophe", "Stagiaire"); foreach (KeyValuePair<string, string> elem in dnom) { stagiaires.Rows.Add(StagiaireID, elem.Key, elem.Value); } // dans des listes string[] nom = { "Jrmy", "Cdric" }; string[] desc = { "Manager", "Manager" }; for (int i = 0; i < nom.Length; i++) { stagiaires.Rows.Add(StagiaireID, nom[i], desc[i]); } // remplissage brut stagiaires.Rows.Add(StagiaireID, "Paul", "Stagiaire"); stagiaires.Rows.Add(StagiaireID, "Quentin", "Stagiaire"); ds.Tables.Add(stagiaires); afficheTable(ds, "stagiaires"); } }
14/09/08
47
6 Conclusion
Vous avez termin ce chapitre sur la gestion de bases de donnes avec ADO.NET. Comme vous avez pu le constater, le mode connect et dconnect ont chacun des utilits ainsi quune utilisation diffrentes. Lquipe ADO.NET.
14/09/08