1. Bases de données .NET en C# (éléments de base)
(document basé sur le Framework .NET 1.1 et Visual Studio 2003)
D'autres documents et exemples concernant la programmation, sur les sites:
www.unvrai.com, jca.developpez.com et www.developpez.com
Introduction
Le but de ce document est d'offrir une base de départ permettant d'aborder plus facilement la gestion
des bases de données telle qu'elle est implémentée dans l'environnement .NET. Ce document n'est, de
loin, pas exhaustif et ne constitue pas un cours. Il est à voir plutôt comme un guide pour débutant, sans
autre prétention que de d'illustrer l'utilisation de quelques techniques liées à la gestion des bases de
données aux travers d'exemples simples. Le contenu est volontairement simplifié et l'objectif devrait être
de présenter diverses situations traitées en ADO.NET. Pour mieux fixer les idées, disons que ces
situations sont censées couvrir ce que l'on peut trouver dans une application autonome et typique en
Access. Toutefois SQL Server sera également abordé.
Afin de permettre à tout un chacun de réutiliser les exemples, ceux-ci utilisent la base de données
COMPTOIR.MDB fournie avec Access (en l'occurrence Access 2003).
Parmi tous les ouvrages qui abordent le sujet des bases de données dans l'environnement .NET, celui
de Gérard Leblanc "C# et .NET", dont les bases de données ne représentent qu'une petite partie des
domaines abordés, est l'un de ceux exposent le mieux le sujet. Ce livre a l'avantage d'être très clair au
niveau technique, mais aussi pédagogique.
Banalités
Les bases de données constituent un des domaines les plus anciens de l'informatique et,
paradoxalement, il est l'un de ceux qui change le moins; notamment en ce qui concerne les bases de
données relationnelles, dont les concepts de base n'ont pas fondamentalement subi de modification
depuis des décennies. Cependant les technologies qui entourent les bases de données (formats,
modes d'accès…), elles, évoluent constamment, à tel point qu'on peut s'y perdre.
ADO.NET est une évolution logique de diverses techniques d'accès aux données, notamment ADO, sur
lesquelles nous n'allons pas revenir. On assiste depuis quelques années au passage d'applications
localisées vers des applications délocalisées ou distribuées. XML prend également une importance
prépondérante dans l'échange d'information. Parallèlement la frontière entre les applications
traditionnelles en bases de données et les applications basées sur internet (par exemple utilisant
ASP.NET) diminue. La tendance est donc, à relativement court terme, de ne plus distinguer les
WebForms et les WinForms.
ADO.NET propose donc un modèle qui intègre les fonctionnalités de XML et de ADO. C'est-à-dire qu'il
offre des ensembles de classes, structures, interfaces, etc faisant partie intégrante du framework .NET
et permettant un accès efficace et cohérent aux données. Les avantages apportés par ADO.NET sont
essentiellement:
• la montée en charge (scalability) pose moins de problèmes qu'auparavant. Par exemple il est
vraiment aisé de dédoubler un serveur web en cas de puissance de traitement accrue. Ceci est
en partie dû à la possibilité de travailler en mode déconnecté avec ADO.NET et d'utiliser des
caches en mémoire.
• l'utilisation abondante de XML, une technologie portable et standardisée permettant des
échanges de données indépendants des systèmes et des plateformes.
• Les facilités offertes au niveau du développement. Le framework .NET, et donc les langages
supportés, ont été pensés et conçus pour intégrer la gestion des bases de données. Visual
Studio intègre tout ce dont le développeur a besoin, quels que soient les types d'applications.
_________________________________________________________________________________________
J-C Armici -1-
2. Il est à noter qu'ADO.NET supporte toutes sortes de de type et de formats de données:
• Des données non structurées
• Des données structurées, mais sous une forme non hiérarchique (CSV, fichiers Excel, fichiers
Exchange, fichiers Active Directory, etc)
• Des données sous forme hiérarchique (XML)
• Des bases de données relationnelles (SQL Server, Oracle, Access, etc)
La compréhension de ADO.NET implique celle des modes connecté et déconnecté. En effet ADO.NET
offre, en plus du mode "habituel", un mode déconnecté. La connexion à une base de données est
l'opération par laquelle un programme se lie à une base de données, locale ou distante. Une connexion
peut être ouverte (pendant que le programme accède aux données) ou fermée. Nous allons décrire
séparément les modes connecté et déconnecté. Le choix d'un mode de travail pour une application
particulière n'est pas toujours évident, chaque mode ayant des avantages et des inconvénients. Bien
comprendre leurs différences devrait faciliter ce choix.
Mode connecté
Dans le mode connecté, une application ouvre une connexion avec une base de données et reste
connectée pendant le traitement des données. Il s'agit du mode le plus répandu et habituel. Dans ce
mode, une application (client) "interagit" avec la base de données (serveur), demande des données, les
modifie et les met à jour au fur et à mesure , avance enregistrement par enregistrement dans une table,
etc. Il y a un lien fort, au sens interactivité du terme, entre le client et le serveur.
Mode déconnecté
Dans le mode déconnecté, une application se connecte à une base de données, rapatrie une partie des
données et se déconnecte de la base de données. S'il s'agit d'une opération de lecture seule (comme
par exemple lors d'une consultation sur un site internet) l'opération est terminée. Si toutefois l'application
doit effectuer des adjonctions ou mises à jour de données, elle doit se reconnecter à la base pour cela.
La notion importante à saisir ici est qu'une partie des données est amenée en mémoire locale du client
pour y être utilisée. Cette partie des données peut être vue comme un sous-ensemble de la base de
données. Il peut s'agir d'une ou plusieurs tables ou fragments de tables, avec ou sans relations. Plus
généralement ce qui peut être exprimé à l'aide d'une ou plusieurs instructions SELECT (en SQL). Ce
mode est particulièrement bien adapté à des applications internet dans lesquelles, par essence, on ne
peut pas imposer une connexion continue à un client. Un utilisateur peut quitter un site ou fermer son
browser de manière impromptue; c'est d'ailleurs le mode de fonctionnement habituel.
Avantages, inconvénients et choix du mode de travail
Nous n'allons pas donner ici des recettes permettant de décider quel mode est le plus adapté à quel
application. L'éventail et la diversité des applications rendent les choses plus subtiles. Et d'ailleurs il est
certainement possible de concevoir une même application aussi bien en mode connecté qu'en mode
déconnecté.
Un principe se dégage toutefois: pour un site internet le mode déconnecté paraît vraiment, dans le
plupart de cas, le plus adéquat.
Attachons-nous maintenant à décrire le principaux avantages et inconvénients des deux modes de
travail
_________________________________________________________________________________________
J-C Armici -2-
3. Avantages
Mode connecté Mode déconnecté
Accès concurrent plus facile à contrôler Bien adapté aux utilisateurs mobiles
Données plus pertinentes (globalement Augmentation des performance et facilité
plus souvent à jour) de montée en charge
Utile dans les cas de consultation de
données
Inconvénients
Mode connecté Mode déconnecté
Nombre d'accès à la base de données et Les données sont moins souvent à jour
trafic réseau plus élevés
Nécessité de résoudre les conflits lors des
mises à jour
Demande de la place mémoire côté client
et plus de subtilité afin d'optimiser la
quantité d'information rapatriée sur le client
Afin de faciliter la compréhension des modes connecté et déconnecté, nous allons simplifier la situation
de la manière suivante:
ADO.NET
Data Provider
Connection
Command DataAdapter
Data
base
DataReader
DataSet
Client (WinForm, WebForm…)
Fig. 1 Modèle ADO.NET simplifié
_________________________________________________________________________________________
J-C Armici -3-
4. Le mode connecté utilise généralement:
• Un objet Connection
• Un objet Command
• Un objet DataReader
Alors que le mode déconnecté fait appel à:
• Un objet Connection
• Un objet DataAdapter
• Un objet DataSet
Voyons plus précisément ce que recouvrent ces divers objets. Tout d'abord, la notion de fournisseur de
données (data provider) recouvre un ensemble de classes spécifiques à une source de données et
fonctionne uniquement avec cette source de données. Son fonctionnement est analogue à celui d'un
pilote (driver) et permet d'effectuer les opérations de base: connexion à la source de données, lecture
des données, mise à jour, etc. Pour le moment il existe quelques fournisseurs de données inclus dans
le framework .NET, mais à terme on trouvera des fournisseurs de données pour la plupart des SGBD.
La figure 2 montre les 4 fournisseurs actuellement pris en charge sous forme de composants (et de
classes):
• xxxDataAdapter
• xxxConnection
• xxxCommand
Où xxx concerne:
• OleDb, par exemple pour accéder aux bases de données Access ou SQL Server (antérieures à
la version 7.0)
• Sql, pour les versions récentes de SQL Server
• Odbc, pour la plupart des SGBD pour lesquels un pilote ODBC existe. Cette possibilité élargit
l'éventail des SGBD supportés
• Oracle, pour l'incontournable SGBD bien connu
Fig. 2 Les SGBD pris en charge dans Visual Studio 2003
_________________________________________________________________________________________
J-C Armici -4-
5. Comme on peut le voir sur le schéma de la figure 1, alors que les objets DataAdapter, Connection,
Command et DataReader sont dépendants du fournisseur de données. Alors que la classe DataSet
est indépendante du SGBD, donc de la source de données, et ses fonctionnalités sont accessibles
quelle que soit l'origine des données dans une application.
Connexion à une base de données
Lors de la connexion à une base de données on doit fournir une chaîne de connexion, qui n'est autre
qu'une chaîne de caractère contenant des paramètres propres à chaque fournisseur de données. On
peut y trouver notamment le nom du fournisseur de données, le chemin de la base de données, le nom
d'utilisateur et le mot de passe, et bien d'autres paramètres. Voici un exemple permettant la connexion à
une base de données Access:
string stConn = @"Data Source=""E:.NETJCADBcomptoir.mdb"";
Provider=""Microsoft.Jet.OLEDB.4.0"";
User ID=Admin";
OleDbConnection Connection = new OleDbConnection(stConn); // connexion OleDb
Bien entendu dans une application réelle le chemin de la base de données ne devrait pas figurer de
manière absolue dans la chaîne de connexion, mais plutôt comme paramètre permettant d'accéder à la
base de données sans devoir recompiler l'application si le chemin d'accès change. Signalons également
que dans le cas ODBC le DSN (Data Source Name) constitue déjà une indirection et les paramètres de
connexion sont définis au niveau du système d'exploitation. De ce fait la chaîne de connexion peut se
résumer à:
string stConn = "dsn=MaBase";
OdbcConnection Connection = new OdbcConnection(stConn); // connexion Odbc
Connection
Comme on peut le voir sur les fragments code précédents, la connexion à la base de données est
généralement créée en spécifiant la chaîne de connexion. Dès ce moment la connexion peut être
ouverte, utilisée, puis fermée.
Command
L'objet Command permet d'interagir avec la base de données au travers de commandes fournies en
SQL. Comme nous le verrons au travers d'exemples, il existe plusieurs variantes pour l'utilisation des
commandes SQL. Voici un exemple montrant utiliser une commande SQL, ici dans le mode déconnecté
avec un DataAdapter:
string stConn = @"Data Source=""E:.NETJCADBcomptoir.mdb"";
Provider=""Microsoft.Jet.OLEDB.4.0"";
User ID=Admin";
String stCmd = "SELECT Contact FROM Clients";
OleDbConnection Connection = new OleDbConnection(stConn); // connexion OleDb
Connection.Open();
OleDbDataAdapter DA = new OleDbDataAdapter(stCmd, Connection);
DataReader
L'objet DataReader, utilisé en mode connecté, permet d'accéder aux données d'une base de données
récupérées par l'intermédiaire d'une commande SQL. Voici une illustration de l'utilisation d'un
DataReader (en mode connecté)
_________________________________________________________________________________________
J-C Armici -5-
6. string stConn = @"Data Source=""E:.NETJCADBcomptoir.mdb"";
Provider=""Microsoft.Jet.OLEDB.4.0"";
User ID=Admin";
string stCmd = "SELECT Contact FROM Clients";
OleDbCommand Cmd;
OleDbConnection Connection = new OleDbConnection(stConn); // connexion OleDb
Connection.Open();
Cmd = new OleDbCommand (stCmd,Connection); // commande pour cette connexion
OleDbDataReader DR = Cmd.ExecuteReader();
if (DR != null)
{
while (DR.Read()) // boucle de lecture
{
listBox1.Items.Add (DR["Contact"]); // ajout dans le listBox
}
}
Connection.Close();
Le mode connecté, avec un DataReader, permet un accès séquentiel, à sens unique (du début vers la
fin) et en lecture seule. Ceci peut paraître restrictif, mais il est bien entendu possible de faire appel aux
commandes SQL INSERT, UPDATE ou DELETE pour le traitement des données.
DataAdapter
Un DataAdapter établit le lien entre une source de données et un DataSet. Il est donc utilisé pour
remplir un DataSet ainsi que pour effectuer la mise à jour des données dans la base de données.
DataSet
La classe DataSet est le composant central du mode déconnecté d'ADO.NET. Comme nous l'avons dit
précédemment, un DataSet correspond à une portion de la base de données, une sorte de cache en
mémoire incluant les données, les relations, les contraintes, etc. Nous en verrons l'utilisation dans
divers exemples.
_________________________________________________________________________________________
J-C Armici -6-
7. Le mode déconnecté
Dans cette partie nous allons voir plusieurs exemples utilisant le mode déconnecté.
Exemple 1:
Dans cet exemple le programme accède à la table Clients de la base de données Access
COMPTOIR.MDB en mode déconnecté. Nous devons ajouter l'accès aux namespaces System.Data et
System.Data.OleDb:
using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
using System.Data.OleDb;
Fig. 3 Remplissage d'un listBox
Nous voulons simplement remplir le listBox avec la liste des noms de clients (champ Contact) de la
table Clients. Pour cela nous faisons appel à un bouton dont voici le code associé:
private void buttonConnection_Click(object sender, System.EventArgs e)
{
string stConn = @"Data Source=""E:.NETJCADBcomptoir.mdb"";
Provider=""Microsoft.Jet.OLEDB.4.0"";
User ID=Admin";
OleDbConnection Connection = new OleDbConnection(stConn); // connexion OleDb
Connection.Open();
OleDbDataAdapter DA = new OleDbDataAdapter("SELECT [Contact] FROM Clients",
Connection);
DataSet DS = new DataSet();
DA.Fill(DS, "Clients"); // remplissage du DataSet
listBox1.DataSource = DS.Tables[0]; // remplissage du listBox
listBox1.DisplayMember = "Contact";
Connection.Close();
}
_________________________________________________________________________________________
J-C Armici -7-
8. Exemple 2:
Dans ce programme, en plus d'un listBox contenant les noms des Clients, nous avons ajouté trois
textBox associés au Code Client, à la Société et au Contact de la table Clients.
Fig. 4 Remplissage d'un listBox et de textBox
Voici le code correspondant au clic sur le bouton "Remplir Clients":
private void buttonConnection_Click(object sender, System.EventArgs e)
{
string stConn = @"Data Source=""E:.NETJCADBcomptoir.mdb"";
Provider=""Microsoft.Jet.OLEDB.4.0"";
User ID=Admin";
string stCmd = "SELECT [Code client], [Société], [Contact] FROM Clients";
OleDbConnection Connection = new OleDbConnection(stConn); // connexion OleDb
Connection.Open();
OleDbDataAdapter DA = new OleDbDataAdapter(stCmd, Connection);
DataSet DS = new DataSet();
DA.Fill(DS, "Clients"); // remplissage du DataSet
listBox1.DataSource = DS.Tables[0]; // remplissage du listBox
listBox1.DisplayMember = "Contact";
textBoxCodeClient.DataBindings.Add("Text", DS.Tables[0], "Code client");
textBoxSociete.DataBindings.Add("Text", DS.Tables[0], "Société");
textBoxContact.DataBindings.Add("Text", DS.Tables[0], "Contact");
Connection.Close();
}
DataBindings est une collection contenant les caractéristiques de la liaison du composant textBox
avec les données.
Remarque:
Les textBox et le listBox étant liés à la même table du même DataSet par l'intermédiaire du
DataAdapter DA, lorsque l'on clique sur une ligne du listBox, le contenu des 3 textBox est
automatiquement synchronisé par rapport à l'enregistrement "pointé" par le listBox.
_________________________________________________________________________________________
J-C Armici -8-
9. Exemple 3:
Ce programme reprend l'idée du programme précédent en modifiant l'emplacement de certaines
instructions et en ajoutant la possibilité de naviguer parmi les enregistrements à l'aide de boutons
Les champs suivants ont été ajoutés dans la définition de Form1:
private CurrencyManager current;
private string stConn = @"Data Source=""E:.NETJCADBcomptoir.mdb"";
Provider=""Microsoft.Jet.OLEDB.4.0"";
User ID=Admin";
private OleDbConnection Connection;
La classe CurrencyManager dérive de BindingManagerBase et permet la synchronisation des
contrôles dépendants dans un WinForm qui sont liés à la même source de données. Le
CurrencyManager gère un pointeur vers l'élément en cour. Ceci permet non seulement de connaître la
position courante, mais également de spécifier cette position.
Dans ce programme on va chercher les données directement au moment du chargement de la fenêtre
(Load)
private void Form1_Load(object sender, System.EventArgs e)
{
Connection = new OleDbConnection(stConn); // connexion OleDb
Connection.Open();
string stCmd = "SELECT [Code client], [Société], [Contact] FROM Clients";
OleDbDataAdapter DA = new OleDbDataAdapter(stCmd, Connection);
DataSet DS = new DataSet();
DA.Fill(DS, "Clients"); // remplissage du DataSet
listBox1.DataSource = DS.Tables[0]; // remplissage du listBox
listBox1.DisplayMember = "Contact";
textBoxCodeClient.DataBindings.Add("Text", DS.Tables[0], "Code client");
textBoxSociete.DataBindings.Add("Text", DS.Tables[0], "Société");
textBoxContact.DataBindings.Add("Text", DS.Tables[0], "Contact");
current = (CurrencyManager)this.BindingContext[DS.Tables[0]]; // indicateur de
// position
}
La fermeture de la connexion est effectuée au moment de la fermeture de la fenêtre:
private void Form1_Closed(object sender, System.EventArgs e)
{
Connection.Close();
}
Les événements suivants répondent au clic sur l'un des 4 boutons de déplacement:
private void btnPrecedent_Click(object sender, System.EventArgs e)
{
current.Position--;
lblCount.Text = current.Position.ToString();
}
private void btnSuivant_Click(object sender, System.EventArgs e)
{
current.Position++;
lblCount.Text = current.Position.ToString();
}
private void btnPremier_Click(object sender, System.EventArgs e)
{
current.Position = 0;
lblCount.Text = current.Position.ToString();
}
_________________________________________________________________________________________
J-C Armici -9-
10. private void btnDernier_Click(object sender, System.EventArgs e)
{
current.Position = current.Count - 1;
lblCount.Text = current.Position.ToString();
}
A noter que lblCount est un label permettant d'afficher le numéro de l'enregistrement courant.
Tout ceci fonctionne bien, mais lorsqu'une ligne est sélectionnée dans le listBox, le numéro de
l'enregistrement courant n'est pas modifié. Pour cela nous faisons appel à l'événement
SelectedItemChanged du listBox afin de récupérer la position courante:
private void listBox1_SelectedIndexChanged(object sender, System.EventArgs e)
{
current.Position = listBox1.SelectedIndex;
lblCount.Text = current.Position.ToString();
}
Fig. 5 Navigation dans les enregistrements
Exemple 4:
Ce programme remplit un DataGrid avec le contenu de la table Clients, en gardant uniquement
quelques colonnes. La définition de la classe Form1 est complétée par:
private string stConn = @"Data Source=""E:.NETJCADBcomptoir.mdb"";
Provider=""Microsoft.Jet.OLEDB.4.0"";
User ID=Admin";
private OleDbConnection Connection;
Et le reste du code est constitué par:
private void Form1_Load(object sender, System.EventArgs e)
{
Connection = new OleDbConnection(stConn); // connexion OleDb
string stCmd = @"SELECT [Code client], [Société], [Contact], [Ville], [Pays], [Fax]
FROM Clients";
Connection.Open();
OleDbDataAdapter DA = new OleDbDataAdapter(stCmd, Connection);
DataSet DS = new DataSet();
DA.Fill(DS, "Clients"); // remplissage du DataSet
dgClients.DataSource = DS;
_________________________________________________________________________________________
J-C Armici - 10 -
11. dgClients.DataMember = "Clients";
}
private void Form1_Closed(object sender, System.EventArgs e)
{
Connection.Close();
}
La propriété DataSource du DataGrid permet de l'associer au DataSet contenant les
enregistrements demandés et la propriété DataMember permet d'indiquer la table concernée.
L'environnement Visual Studio permet une multitude de paramétrage de propriétés concernant l'aspect
du DataGrid; en voici le résultat:
Fig. 6 Utilisation d'un DataGrid
Remarque:
Il est important de noter que le nom donné au contenu du DataSet peut être différent de celui
de la table de la base de données: Au lieu de Clients nous pouvant utiliser un autre nom, par
exemple Cli:
string stCmd = @"SELECT [Code client], [Société], [Contact], [Ville], [Pays], [Fax]
FROM Clients";
Connection.Open();
OleDbDataAdapter DA = new OleDbDataAdapter(stCmd, Connection);
DataSet DS = new DataSet();
DA.Fill(DS, "Cli"); // remplissage du DataSet
dgClients.DataSource = DS;
dgClients.DataMember = "Cli";
De plus, si l'un des enregistrements est modifié dans le DataGrid:
_________________________________________________________________________________________
J-C Armici - 11 -
12. Fig. 7 Modification des données
On peut le valider, mais cette validation sera uniquement valable dans le DataSet. Et
rappelons qu'on est en mode déconnecté et tant qu'aucune opération de mise à jour n'est
effectuée sur la base de données, les modifications ne sont pas reportées. En d'autres termes,
comme le DataSet réside en mémoire, après la fin de l'exécution du programme toute
modification, suppression, insertion sont perdues.
Exemple 5:
Ce programme est une variante du précédent permettant à l'utilisateur de spécifier où se trouve la base
de données Comptoir.mdb. Pour cela on fait appel à un openFileDialog que l'on place sur la
fenêtre de l'application. Afin d'extraire le nom du fichier de openFileDialog1.FileName on fait appel
à la classe FileInfo définie dans System.IO:
using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
using System.Data.OleDb;
using System.IO;
Au niveau de Form1 on définit également les champs:
private string stConn = "Provider=Microsoft.Jet.OLEDB.4.0;User ID=Admin";
private OleDbConnection Connection;
Le reste devient:
private void Form1_Load(object sender, System.EventArgs e)
{
string fName;
openFileDialog1.Filter = "Fichiers Access (*.mdb)|*.mdb";
openFileDialog1.InitialDirectory = Application.StartupPath;
openFileDialog1.Title = "Chemin de la base de données 'Comptoir.mdb'";
openFileDialog1.FileName = "comptoir.mdb";
if (openFileDialog1.ShowDialog() == DialogResult.OK)
{
fName = new FileInfo(openFileDialog1.FileName).Name.ToUpper();
if ( fName != "COMPTOIR.MDB") // test bonne base de données
return;
fName = openFileDialog1.FileName;
_________________________________________________________________________________________
J-C Armici - 12 -
13. stConn = "Data Source=" + fName + ";" + stConn;
string stCmd = @"SELECT [Code client], [Société], [Contact], [Ville], [Pays], [Fax]
FROM Clients";
Connection = new OleDbConnection(stConn); // connexion OleDb
Connection.Open();
OleDbDataAdapter DA = new OleDbDataAdapter(stCmd, Connection);
DataSet DS = new DataSet();
DA.Fill(DS, "Clients"); // remplissage du DataSet
dgClients.DataSource = DS;
dgClients.DataMember = "Clients";
}
}
private void Form1_Closed(object sender, System.EventArgs e)
{
if (Connection != null)
Connection.Close();
}
La boîte de dialogue suivante apparaît au lancement de l'application:
Fig. 8 Recherche de 'Comptoir.mdb'
Exemple 6:
Cet exemple montre comment utiliser un assistant de création de fenêtre liée à une base de données. Il
permet de bien comprendre, au travers du code généré par l'assistant, les mécanismes du mode
déconnecté lors des opérations de mise à jour, ajout ou suppression.
Voici comment procéder:
• Dans un premier temps il faut créer un nouveau projet sous forme d'une application Windows en
C#
_________________________________________________________________________________________
J-C Armici - 13 -
14. • Dans le menu contextuel du projet (ici Access6), choisir d'ajouter un nouvel élément:
Fig. 9 Ajout d'un nouvel élément au projet
• Dans la boîte de dialogue qui apparaît, choisir "Assistant formulaire de données"
Fig. 10 Lancement de l'assistant
• Il faut ensuite suivre les étapes:
_________________________________________________________________________________________
J-C Armici - 14 -
15. Fig. 11 Démarrage de l'assistant
• Créer ensuite un nouveau groupe de données (ici DSClients)
Fig. 12 Choix d'un groupe de données (DataSet)
• Il faut ensuite choisir une connexion de données. Si la connexion désirée n'a encore jamais été
utilisée dans un projet en Visual Studio, il faut cliquer sur le bouton "Nouvelle connexion…"
_________________________________________________________________________________________
J-C Armici - 15 -
16. Fig. 13 Choix d'une connexion de données
• Pour une nouvelle connexion il faut parcourir les différents onglets (essentiellement les deux
premiers) de la fenêtre suivante:
Fig. 14 Spécification d'une nouvelle connexion
_________________________________________________________________________________________
J-C Armici - 16 -
17. • Après avoir spécifié la base de données à utiliser, on se retrouve avec la fenêtre de la figure15,
et en cliquant sur le bouton "Suivant" on peut choisir une ou plusieurs tables ou vues:
Fig. 15 Choix du contenu du groupe de données
• Après avoir cliqué sur le bouton "Suivant", on obtient:
Fig. 16 Choix des champs (colonnes) à afficher
_________________________________________________________________________________________
J-C Armici - 17 -
18. • Après avoir cliqué sur le bouton "Suivant", on peut choisir le style d'affichage (ici un
enregistrement à la fois) ainsi que la présence de divers boutons (Ajouter, Supprimer,…)
Fig. 17 Choix du style d'affichage
• Finalement on obtient la fenêtre suivante, en mode conception. On remarque les trois
composants ajoutés automatiquement par l'assistant:
Fig. 18 Résultat généré par l'assistant
_________________________________________________________________________________________
J-C Armici - 18 -
19. • Le résultat final est simple, mais fonctionnel:
Fig. 19 Visualisation des données
Remarque:
Si, à l'étape de la figure 15 nous avions choisi deux tables, par exemple Clients et Commandes,
nous aurions eu droit à la fenêtre suivante permettant de spécifier la relation entre les tables afin
que le code produit automatiquement par l'assistant puisse effectuer correctement la
synchronisation entre table parent et table enfant.
Fig. 20 Spécification des relations
_________________________________________________________________________________________
J-C Armici - 19 -
20. Le résultat obtenu serait alors le suivant:
Fig. 21 Exemple de formulaire avec sous-formulaire
Voilà donc un exemple concret montrant le mode déconnecté en fonction. Il y a fonctionnellement peu
de différences entre ce programme et un formulaire équivalent écrit, par exemple, en Access.
Il peut être intéressant de mettre cet assistant à contribution, au moins pour bénéficier du code généré.
Quant à l'aspect un peu austère de l'interface utilisateur, le développeur aura tout loisir de le rendre plus
évolué esthétiquement ou ergonomiquement. On dispose donc d'une bonne base de départ pour
élaborer un vrai projet, même complexe.
Bases de données et XML
XML (Extensible Markup Language) est un standard ouvert de stockage d'information, un format de
fichier lisible (sous forme de texte) et simple, basé sur le principe du balisage. XML prend de plus en
plus d'importance, à tel point que plusieurs SGBDR, dont SQL Server, peuvent l'utiliser comme format
de stockage de données. Dans le framework .NET XML est omniprésent, explicitement ou
implicitement. Dans la gestion des bases de données mettant en jeu des DataSet, XML est le support
sous-jacent de la représentation des données, ce qui permet notamment une communication aisée avec
les services web dont l'échange de données s'effectue précisément en XML.
_________________________________________________________________________________________
J-C Armici - 20 -
21. L'étude complète de XML et des éléments qui lui sont associés ne va pas être abordée ici. Bien que sa
structure soit simple et facile à comprendre, il est rare que l'on doive écrire à la main du code XML;
Plusieurs classes de .NET possèdent des méthodes permettant de lire et de générer facilement de
données au format XML. On peut donc travailler avec XML sans vraiment en maîtriser tous les aspects.
Dans les exemples qui précèdent nous avons abordé le travail avec une base de données de manière
"classique", en créant les divers objets, par exemple les DataSet, de façon dynamique. Nous allons voir
maintenant comment aborder les bases de données, toujours en mode déconnecté, de manière plus
"moderne" par rapport aux outils de développement existants.
Exemple 7:
Cet exemple met en œuvre une approche légèrement différente pour travailler avec une table d'une
base de données Access, utilisant notamment un DataSet typé.
Après avoir créé un nouveau projet C# (application Windows), un DataGrid est placé dans la fenêtre de
l'application:
Fig. 22 Fenêtre principale avec un DataGrid
Après avoir fait afficher l'onglet "Explorateur de serveurs" (Ctrl-Alt-S) on peut voir une situation analogue
à celle-ci:
Fig. 23 Explorateur de serveurs
_________________________________________________________________________________________
J-C Armici - 21 -
22. En fonction de des projets précédemment créés des connexions existantes sont montrées. Si la
connexion qui nous intéresse ne figure pas dans la liste, il faut l'ajouter à l'aide d'un clic droit sur
"Connexions de données", puis "Ajouter une connexion…"
Fig. 24 Ajout d'une nouvelle connexion
Dans notre cas, comme la connexion à la base de données Comptoir.mdb existe, il suffit de déployer
l'arborescence jusqu'à atteindre la liste des tables de cette base de données:
Fig. 25 Liste des tables
A l'aide du glisser-déplacer (drag and drop) on amène la table Clients sur la fenêtre de l'application.
Visual Studio crée alors les deux objets
Fig. 26 Connexion et adapteur
A ce stade nous allons créer un DataSet à l'aide d'un clic droit sur le projet, dans l'explorateur de projet.
Dans l'option "Ajouter un nouvel élément…" nous choisissons d'ajouter un DataSet comme le montre la
figure 27:
_________________________________________________________________________________________
J-C Armici - 22 -
23. Fig. 27 Ajout d'un DataSet
Ceci crée un nouveau fichier Dataset1.xsd dans le projet.
Fig. 28 Ajout d'un DataSet
De plus l'onglet suivant est affiché et va nous permettre de spécifier le contenu du DataSet
Fig. 29 Préparation à la spécification de la structure du DataSet
Comme l'indique la note figurant dans cette fenêtre nous allons faire un glisser-déplacer de la table
Clients, depuis l'explorateur de serveurs vers cette fenêtre. Voici ce qui apparaît alors:
_________________________________________________________________________________________
J-C Armici - 23 -
24. Fig. 30 représentation graphique de la structure du DataSet
En réalité la structure du DataSet est décrite sous forme XML (voir figure 31), mais Visual Studio nous
la montre également sous une forme plus visuelle. D'ailleurs l'onglet XML au bas de cette fenêtre
montre le contenu du fichier Dataset1.xsd.
<?xml version="1.0" encoding="utf-8" ?>
<xs:schema id="Dataset1" targetNamespace=http://tempuri.org/Dataset1.xsd
elementFormDefault="qualified" attributeFormDefault="qualified"
xmlns="http://tempuri.org/Dataset1.xsd"
xmlns:mstns="http://tempuri.org/Dataset1.xsd"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xs:element name="Dataset1" msdata:IsDataSet="true">
<xs:complexType>
<xs:choice maxOccurs="unbounded">
<xs:element name="Clients">
<xs:complexType>
<xs:sequence>
<xs:element name="Code_x0020_client" type="xs:string" />
<xs:element name="Société" type="xs:string" minOccurs="0" />
<xs:element name="Contact" type="xs:string" minOccurs="0" />
<xs:element name="Fonction" type="xs:string" minOccurs="0" />
<xs:element name="Adresse" type="xs:string" minOccurs="0" />
<xs:element name="Ville" type="xs:string" minOccurs="0" />
<xs:element name="Région" type="xs:string" minOccurs="0" />
<xs:element name="Code_x0020_postal" type="xs:string" minOccurs="0" />
<xs:element name="Pays" type="xs:string" minOccurs="0" />
<xs:element name="Téléphone" type="xs:string" minOccurs="0" />
<xs:element name="Fax" type="xs:string" minOccurs="0" />
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:choice>
</xs:complexType>
<xs:unique name="Dataset1Key1" msdata:PrimaryKey="true">
<xs:selector xpath=".//mstns:Clients" />
<xs:field xpath="mstns:Code_x0020_client" />
</xs:unique>
</xs:element>
</xs:schema>
Fig. 31 Structure du DataSet sous forme XML
_________________________________________________________________________________________
J-C Armici - 24 -
25. Nous allons maintenant générer le DataSet en sélectionnant oleDbDataAdapter1 (visible sur la figure
26) et en cliquant sur "Générer le groupe de données…" apparaissant sous la fenêtre des propriétés:
Fig. 32 Option pour générer le DataSet
Dans notre cas le DataSet existe, il s'agit de Dataset1 et nous choisissons la table Clients. A noter
qu'il est également possible de choisir un nouveau DataSet.
Fig. 33 Choix du DataSet
Nous devons maintenant lier les données provenant de ce DataSet (donc de la table Clients) avec le
DataGrid qui se trouver dans la fenêtre de l'application. Pour cela il faut sélectionner le DataGrid, et lui
affecter une source de données (DataSource).
Fig. 34 Choix de la source de données
_________________________________________________________________________________________
J-C Armici - 25 -
26. En déroulant la liste concernée nous trouvons dataset11.Clients qui est précisément la source de
données que nous souhaitons afficher. Les entêtes de colonnes sont alors affichés dans la grille:
Fig. 35 Grille associée au DataSet
Afin que les données puissent être affichées, il faut encore écrire le code permettant de remplir le
DataSet. Pour cela, nous plaçons un bouton sur la fenêtre, sur le clic duquel nous définissons le code
événementiel suivant:
private void btnCharger_Click(object sender, System.EventArgs e)
{
oleDbDataAdapter1.Fill (dataset11.Clients);
}
Après le lancement de l'application, le clic sur le bouton permet d'afficher les données:
Fig. 36 Affichage des données
_________________________________________________________________________________________
J-C Armici - 26 -
27. Remarque:
Le contenu de ce document se rapporte à Visual Studio 2003. L'arrivée du Framework .NET 2.0
et de Visual Studio 2005 (tous deux en version beta 2 actuellement) apporte une somme
considérable de nouveautés et d'améliorations, tant au niveau du langage qu'au niveau des
outils de développement. Les bases de données ne sont pas en reste.
Bien qu'en principe le nouveau cru 2005 soit compatible avec la version précédente, le mode de
travail du développeur a été en partie modifié. Un nouveau document consacré aux bases de
données dans l'environnement .NET devrait donc bientôt apparaître. A suivre…
_________________________________________________________________________________________
J-C Armici - 27 -