Visual Basic et Bases de Données ADO.NET
Visual Basic et Bases de Données ADO.NET
(Résumé)
Le concept de « Base de Données » est largement utilisé dans tous les domaines qui
impliquent l’informatique. Visual Basic est, par excellence, un langage qui facilite le travail
avec ce concept. Avant de commencer à présenter les liaisons entre VB et les bases de
données, faisons une brève introduction au concept de base de données.
Une base de données est une structure spécialement conçue pour la gestion de
grandes quantités de données. Par gestion on comprend l’ajout, la suppression, la modifi-
cation et l’utilisation (calculs, manipulations, sélections, affichage, etc..) de données de
différents types. D’une base à l’autre, les types de données peuvent être différents. Par
exemple dans une base de type Access il existe le type booléen (par exemple Vrai/Faux ou
Oui/Non, etc.) tandis que dans une base de type MSSQL ce type n’existe pas et, donc, il
faudrait le remplacer par un autre − char*1 ("V"/"F") ou même entier (0/-1). La façon
d’enregistrer les données ainsi que la façon de lire les données peut différer d’un type de
base à l’autre. À cause des différences entre les bases de données, la manière avec laquelle
on travaillera sera aussi différente.
Dans ce texte, nous allons analyser les liaisons entre VB et les bases de données
relationnelles. Parmi les bases de données relationnelles nous prendrons l’exemple de
Access.
La base «BaseTP4.MDB»
Cette base de données est constituée de 3 tables, trois ensembles de données
regroupées, l’une contenant les données sur les étudiants inscrits, une autre sur les
départements d’attache de ces étudiants et la dernière sur les groupes où sont classés les
étudiants.
La table IFT1175 :
Nom du champ Type de données
NOM Texte (maximum 33 caractères)
CODEPERM Texte (maximum 12 caractères)
GROUPE Octet
Num DEPT Entier long (= entier en VB.NET)
REMARQUE Texte (maximum 20 caractères)
INTRA
FINAL 3 données numériques (réelles doubles)
TP
On notera que la fiche de l’étudiant contient le «numéro» du département plutôt que le nom
du département et le numéro de groupe plutôt que sa description. Notez aussi que le nom du
champ «Num Dept» contient un espace, ce qui est permis en Access.
La table Groupes :
Nom du champ Type de données
NumGroupe Entier long. Correspond au champ «GROUPE» de la table
«IFT1175»
Description Texte (max. 20 caractères) décrivant le groupe : ex. «Mardi AM».
On pourra donc aller chercher des données soit dans une table (ex. «Liste des nom des
étudiants avec leur note de l'intra») ou dans plusieurs tables (ex. «Liste des étudiants dont le
nom du département est "Chimie"» ou bien «Liste des étudiants (Nom et Code permanent)
avec le nom de leur département et l'horaire de leur cours».
Classes OleDb
L'ensemble de la technologie OLE DB, intégrée au FrameWork.NET, permet au
programmeur de créer des commandes qui sont indépendantes des bases de données
utilisées en passant par les différents objets intermédiaires qui servent alors d'interface. On
change de base ? On ajuste les interfaces et on n'a pas à modifier le programme.
Classe OleDbConnection
Un objet de cette classe possède une propriété fondamentale de type «String», la
«ConnectionString» qui décrit à la fois le type de liaison (le moteur de recherche et le fichier
ou base à ouvrir). Supposons que la variable «String» contient un texte adéquat, alors on
peut écrire
Dim UneConn As OleDbConnection
UneConn = New OleDbConnection
UneConn.ConnectionString = UneChaine
UneConn.Open() ' Méthode qui «ouvre» la connexion.
ou, plus brièvement, en utilisant le constructeur «New»
Dim UneConn As OleDbConnection = New OleDbConnection(UneChaine)
UneConn.Open() ' Méthode qui «ouvre» la connexion.
qui ouvrira alors la connexion. En cas d'erreur dans la chaîne de correction, il y aura
interruption du programme avec un message de VB.
À partir de ce moment, on peut utiliser deux ou trois classes d'objets pour, ou bien lire
les données de la base, ou bien les modifier et les mettre à jour.
Après la lecture des données, on peut bien sûr fermer la connexion avec
UneConn.Close()
Propriété ConnectionString
Si on ne connaît pas le libellé de la chaîne de connexion adéquate, on peut utiliser un
outil développé en VB6 pour la définir facilement : le fichier «XXX.udl». Un fichier de type
«Universal Data Link» contient une chaîne de connexion qui peut être modifiée par un
éditeur «Assistant des liaisons de données.
5. Selon le type de base, les autres onglets serviront à définir l'environnement de l'accès,
comme le mot de passe, les permissions partagées, etc. Dans le cas d'une simple
base Access, les deux premiers onglets peuvent suffire.
6. Dans l'onglet «Fournisseur», on sélectionne «Microsoft Jet xx OLE DB Provider».
7. Dans l'onglet «Connexion», on peut taper le nom de la base ou bien naviguer sur
l'ordinateur (bouton [...]) pour localiser la base. Si on désire que le fichier soit en
adressage relatif, il faut supprimer le chemin pour ne laisser que le nom.
8. Après avoir fermé l'application, il suffit d'ouvrir le fichier avec WordPad, NotePad ou
tout autre éditeur de texte et vous y trouverez la chaîne de connexion qu'il suffira de
«Copier/Coller» dans votre programme VB :
[OleDb]
; Everything after this line is an OLE DB initstring
Provider=Microsoft.Jet.OleDb.4.0;Data Source=BaseTP4.mdb;Persist Security Info=False
Vous noterez que le nom du fichier peut varier d'une application à l'autre. C'est
pourquoi on peut séparer la chaîne en trois sections : le nom de la base, la partie qui le
précède et la partie qui le suit. On peut alors reconstituer la chaîne en concaténant les trois
parties avant de l'utiliser.
Classe OleDbDataReader
L'objet de classe «OleDbDataReader» est une interface vers les données permettant
d'accéder séquentiellement aux données obtenues à partir de l'objet précédent, de classe
OleDbCommand. Il s'utilise avec une requête dont l'effet est de ramener un jeu
d'enregistrements, c'est-à-dire une séquence de lignes d'une table dont les colonnes sont les
champs de la base de données. On l'obtient comme suit :
Dim UnDataReader As OleDbDataReader
UnDataReader = UneCommande.ExecuteReader()
L'objet «DataReader» fonctionne tout à fait comme un objet de classe
«StreamReader» : il possède une méthode booléenne «Read()» et chaque appel à cette
méthode place le prochain enregistrement dans une variable cachée (de type Collection) à
laquelle nous donne accès la propriété publique «Item(index)».
Par exemple, supposons que la requête
«SELECT CodePerm, Nom, Intra, Final FROM IFT1175 WHERE [Num DEPT] = 12»
placée dans l'objet «UneCommande» ci haut ait pour effet de ramener le bloc d'enregis-
trement suivant de la base de données reliée, soit trois enregistrements des quatre champs
«CodePerm», «Nom», «Intra» et «Final».
Classe OleDbConnection
On utilisera ici aussi l'outil de connexion déjà utilisé à l'étape précédente. Se rappeler
simplement les deux éléments essentielles de la propriété principale (ConnectionString) de
cet objet : le fournisseur de service et le nom de la base utilisée.
Dans le cas des mises à jour, ADO.NET prévoit que la connexion est établie, que les
données sont transférées en mémoire et que la connexion est immédiatement fermée. Ainsi,
on évite de surcharger le réseau dans le cas d'une base centralisée (ce qui est le plus
souvent le cas dans les applications commerciales des bases de données). Une fois les
mises à jour effectuées localement en mémoire, la connexion est ré ouverte, les données
modifiées retransmises dans la base et la connexion refermée.
Classe OleDbDataAdapter
L'objet de cette classe (un DataAdapter) constitue le coeur de l'interface (le pont)
entre la base de données et le programme. C'est celui qui transfère les information entre la
base et l'application en convertissant au besoin les données de façon à ce qu'elles puissent
être traitées localement comme s'il s'agissait d'une base de données relationnelle, quel
que soit leur format dans la source. Les deux propriétés qui permettent d'aller chercher les
données sont les mêmes que pour le «OleDbCommand», soit la connexion
(OleDBConnection) et la chaîne SQL sous forme de variable ou constante, ou sous forme
d'une commande OleDbCommand. :
Dim UnAdapt As New OleDbDataAdapter("unechaineSQL", UneConn)
Dim UnAdapt As New OleDbDataAdapter(UneCommande, UneConn)
La chaîne SQL utilisée sera placée dans la propriété «SelectCommand» et permettra
de transférer les informations de la base de données vers la zone de mémoire où résidera la
copie. La méthode «Fill» pourra effectuer ce travail (voir plus loin). Mais pour mettre à jour la
base, il faudra en plus transférer les données dans l'autre sens (méthode «Update») et pour
cela, il faudra définir les commandes SQL de suppression, d'ajout et de modification des
enregistrements. On peut définir ces commande (si on les connait) dans les propriétés
suivantes :
UnAdapt.DeleteCommand = "UneChaineSQL2"
UnAdapt.InsertCommand = "UneChaineSQL3"
UnAdapt.UpdateCommand = "UneChaineSQL4"
Une fois que les 4 chaînes SQL sont définies, les méthodes «Fill» et «Update» du
DataAdapter transféreront les informations dans un sens et dans l'autre.
Un DataSet n'a pas de méthode pour «aller chercher» des données. Il «attend» qu'on
(le DataAdapter) les lui donne «UnAdapt.Fill()». Une fois une ou des tables ajoutées à sa
collection, on peut y accéder par le rang (base 0) ou par le nom. qu'on a donné à la table.
Comme la propriété «Item» est la propriété de défaut de Tables, les énoncés suivants seront
équivalents si le nom de la première table est «MaListe» :
Dim UneTable As DataTable = UnDataSet.Tables.Item(0)
Dim UneTable As DataTable = UnDataSet.Tables.Item("MaListe")
Dim UneTable As DataTable = UnDataSet.Tables(0)
Dim UneTable As DataTable = UnDataSet.Tables("MaListe")
Classe DataView
Les objets «DataView» sont aussi des jeux d'enregistrements. Mais une «vue»
(comme une requête en Access) permet de réorganiser les données de la table par exemple
en les triant, ou bien en filtrant des données. Exemple, ne prendre de la table que les
enregistrements où le champ "Intra" est plus grand que le champ "Final" et «sortir» la liste en
ordre alphabétique.
Dim UneVue As New DataView(MaTable)
UneVue.RowFilter = "Intra < Final" ' Les champs doivent exister
UneVue.Sort = "Nom"
L'utilisation de UneVue se fera de la même manière que MaTable sauf que les
enregistrements seront présentés différemmant.
En tradition avec les versions précédentes de Visual Basic, VB.NET offre des «outils
automatiques» et des assistants pour les ajuster, le but étant de définir une connexion à la
base sans avoir à la programmer. Pour ce faire, VB met à la disposition du programmeur une
section de la boîte d'outils intitulée «Données» (Data) contenant la plupart des classes déjà
vues sous forme de contrôles.
Plutôt que de créer la liste des objets à l'exécution, on peut définir chaque étape des
la liaison avec les contrôles au moment du «design». L'«assistant» présente des boîtes de
dialogue où il suffit de fournir les principales informations demandées. Parmi les classes
d'objets disponibles, on note les classes déjà rencontrées, soit les OleDBConnection, les
OleDBCommand. les OleDbDataAdapter, les DataSet et les Dataview avec en plus
la classe DataGrid qui permet l'affichage intégral d'un jeu d'enregistrements.
Bien que tous ces objets puissent être créés lors de l'exécution du programme,
le fait de pouvoir les définir en mode Design facilite la tâche par l'utilisation des
fenêtres de propriétés et des boîtes de dialogue des assistants.
Schéma général
On peut schématiser ainsi la chaîne des relations entre les différents objets entre les
données de la base et la grille d'affichage sur la feuille :
Connexion Q DataAdapter Q DataSet Q DataGrid
En plaçant un DataAdapter sur la feuille, un assistant est lancé qui pourra définir ET
la connexion (chaîne de connexion), ET la source des données (chaîne SQL). Ensuite il n'y
aura plus qu'à ajouter sur la feuille, le DataSet et la DataGrid et d'établir les liens entre eux.
Classe DataGrid
Le point central de l'opération est certes l'utilisation du contrôle DataGrid car celui-ci
peut afficher directement un jeu de caractère quelconque. Mieux, comme il s'agit d'un
contrôle «dynamique», il suffit de lui affecter un jeu d'enregistrement pour qu'il s'adapte à
celui-ci. En effet, le nombre, le titre et la largeur des colonnes est défini en fonction du jeu
d'enregistrement qui l'alimente. Mieux, si on lui affecte plus d'un jeu d'enregistrements, le
DataGrid se retrouve muni d'un bloc d'onglets permettant de choisir laquelle des tables
correspondantes sera affichée.
L'information ne circule pas directement du DataGrid vers la base : elle doit transiter
par une Table d'un DataSet. La propriété DataSource du DataGrid permettra donc de faire le
lien avec le DataSet utilisé et avec la table qui s'y trouve.
Enfin, la faiblesse actuelle du contrôle est la difficulté d'en modifier le format, ce qui
sera sûrement amélioré lors d'une prochaine version de VB.NET. Notez cependant qu'une
fois les données affichées, l'utilisateur peut gérer la largeur des colonnes et trier les
informations sur chacune de celles-ci, au choix, en cliquant sur la tête de colonne.
Classe OleDbConnection
Bien que l'objet de classe OleDbConnection existe dans la boîte d'outils, on
l'utilisera rarement puisque l'assistant DataAdapter permettra soit d'utiliser une connexion
déjà établie, soit d'en créer une nouvelle. Notez qu'une même connexion peut servir à
plusieurs «DataAdapter».
Classe OleDbDataAdapter
En déposant sur la feuille un contrôle
OleDbDataAdapter (que ce soit par glissement ou
par double-clic), on lance un «Assistant Configuration
d'adaptateur de données» qui permettra de créer la
liaison avec les données de façon interactive. De fait,
l'assistant permettra de désigner le fournisseur de la
base, de pointer vers le fichier (base de données) et
donc de créer coup sur coup la chaîne de connexion
ET la chaîne SQL, le tout de manière interactive.
La première
étape de l'assistant
consiste à désigner
soit une connexion
existante (déjà
définie) ou d'en
créer une nouvelle.
Dans ce dernier
cas, il fonctionne
tout comme lors de
la création d'un lien
dynamique de
données (voir plus
haut, les fichiers
«UDL») en permet-
tant de choisir le fournisseur et la base de données.
Classe DataSet
Pour chaque grille, on ajoutera un contrôle DataSet qui pourra recevoir le jeu
d'enregistrement défini par la chaîne SQL de chaque DataAdapter. Une fois la grille
associée au DataSet, il n'y aura plus qu'à commander le déplacement des informations de la
base au DataSet, donc vers la grille, et de la grille (via le DataSet) vers la base de données.
Attention cependant! Comme ADO.NET est basé sur le traitement indépendant des
données en mémoire, il faudra procéder au transfert PAR PROGRAMMATION. Pour ce faire,
le DataSet possède une méthode Fill(UnDataSet, "nom_d'une_table") qui ouvre la
connexion, lance l'appel à la requête SQL «SELECT... », place le jeu d'enregistrements dans
la table nommée et referme la collection. Comme le DataGrid est lié à la table, les
informations y sont directement accessibles. On utilise cette méthode lors du chargement de
la feuille ou bien en cours d'exécution (via un bouton de commande) chaque fois que l'on
désire recharger les informations de la base (par exemple si une autre grille y a placé des
mises à jour).
En parallèle, si le DataAdapter a pu générer les requêtes SQL adéquates, lors la
méthode Update(UnDataSet, "nom_d'une_table") ou Update(UnDataSet) mettra à jour les
informations contenue dans une table ou dans toutes les tables du Dataset au moyen de ces
chaînes SQL. Le DataAdapter ne transférera bien sûr que les enregistrement modifiés et la
méthode retournera une valeur entière représentant le nombre d'enregistrements touchés
(créés, modifiés ou supprimés). Ici aussi, la connexion sera ouverte et refermée
automatiquement.
On utilisera cette méthode soit à la fermeture de l'application, soit au besoin au moyen
d'un bouton de commande.