Gestion des données visual basic 2008 et sql server ce

Gestion des données Visual Basic 2008 et SQL Server CE

Description

Bonjour à tous,

Répondant souvent aux questions sur le forum, je m'aperçois que beaucoup de personnes utilisent Excel ou Access comme base de données locale. C'est pourquoi j'ai décidé de faire ce tutoriel vous démontrant comment utiliser une formule simple pour les applications de données locales qui n'est autre que Visual Basic.Net + SQL Serveur CE.

Je vais donc vous proposer de réaliser une application exemple, manipulant des données en local, étapes par étapes, de la création de la base jusqu'au déploiement. Cette application sera un simple formulaire de gestion des contacts.

Ce tutoriel fait une cinquantaine de pages et s'adresse aux novices et aux développeurs ayant des bases en VB.Net.

Vous en trouverez la source sur vbfrance ici.

Qu'allez-vous appendre en lisant ce tutoriel ?

  • Créer une base de données SQL CE
  • Manipuler ADO.Net en Visual Basic
  • Tirer profit des nombreux outils et assistants de Visual Studio.
  • Déployer un programme de données.

Cette application vous montrera les grandes lignes de la gestion des données en ADO.Net avec une base de données SQL CE.

Introduction

Tout d'abord, nous commencerons par créer un nouveau projet Winform à l'aide de Visual Basic.

Figure1, Concepteur Winform

Figure2, Explorateur de solutions.

Comme vous pourrez le voir si vous en avez l'habitude, Visual Basic vous crée par défaut un formulaire nommé « Form1 » (Fig. 1) et vous affiche celui-ci dans le concepteur (Fig. 2). Nous allons donc poursuivre en ajoutant une base de données locale à notre projet. Pour se faire :

  • Clic sur le menu « Projet »
  • Clic sur « Ajouter un nouvel élément »

Vous devriez voir une boîte de dialogue vous permettant d'ajouter divers éléments à votre projet (Fig. 3). Choisissez « Base de données locale » puis dans le champ « Nom » saisissez « MaBaseLocale ».

Figure3, Ajout d'un nouvel élément au projet.

Ceci fait, une boîte de dialogue de configuration des bases de données vous proposera la création d'un DataSet fortement typé comme le montre la figure N°4. Saisissez dans le champ nom du formulaire « MonDataSet » puis terminez l'assistant.

Figure4, Assistant de configuration des données.

Figure5, Explorateur de solution, Base et DataSet.

Vous devriez maintenant apercevoir dans votre explorateur de solution votre base de données (MaBaseLocale.sdf) et votre DataSet fortement typé (MonDataSet.xsd) figure 5. Nous allons pouvoir passer à l'étape suivante.

Création du modèle de données

Pour poursuivre, nous allons définir les tables et les champs qui composeront notre base de données. Le but étant de vous initier et non de créer un programme complexe, notre base ne comportera qu'une table, qui servira pour le stockage des contacts.

En tant normal, nous serions obligés d'éditer notre base de données via un utilitaire spécifique (tel que Microsoft SQL Management Studio). Mais fort heureusement Visual Basic, intègre un petit éditeur de bases de données.

Pour continuer, double-cliquez sur le fichier « MaBaseLocale.sdf » dans l'explorateur de solution (fig. 5). Vous devriez voir apparaitre l'explorateur de bases de données (Explorateur de serveurs sous Visual Studio) sur la gauche de l'EDI comme le montre la figure N°6.

Figure 6, Explorateur de bases de données.

Faite un clic avec le bouton droit de votre souris sur le noeud « Table » de l'explorateur de bases de données, puis choisir « Créer la table » dans le menu qui s'affiche.

Figure 7, Editeur de table de Visual Studio.

Dans l'éditeur de tables ci-dessus, saisissez dans le champ « Nom » le nom de notre table qui sera « Contacts ». En dessous, dans les champs vides, créez une nouvelle colonne en saisissant « ID » pour le nom de colonne et changer le type de données pour « uniqueidentifier » (qui correspond au type GUID en Visual Basic).

Par la suite changez la valeur pour « Oui » dans la colonne « Clé primaire ».

En dessous, dans la valeur par défaut de notre colonne n'oubliez pas de saisir la valeur « newid() », si vous ne savez pas encore pourquoi, vous devez peut être vous en douter, mais nous reviendrons la dessus plus tard.

Figure 8, Notre table au complet.

Ceci fait, il vous restera à créer les autres champs en respectant le modèle de la figure 8. Créez tous les champs, modifiez leur type de données, leur longueur et n'autorisez pas les valeurs nulles pour les champs « nom » et « prenom ». Vous pouvez en suite fermer cet éditeur en cliquant sur le bouton OK, vous devriez normalement avoir le schéma de table démontré dans la figure 9, après avoir étendue les noeuds de la table contacts.

Figure 9, Schéma de table.

Les requêtes SQL

Le langage SQL tiré de l'anglais Structured Query Language ou langage de requêtes structurés, est un langage de programmation à part entière tel que Visual Basic ou le C++ mais orienté vers l'accès aux données, qui permet d'abord d'émettre des requêtes vers un serveur de données et de pouvoir en récupérer le résultat. Mais ce n'est pas tout, il permet aussi de pouvoir stocker des procédures à l'intérieur de notre base pour l'exécuter au moment voulu. Le langage SQL permet entre autre de travailler sur les bases de données du serveur, mais aussi sur le serveur lui-même pour permettre sa configuration ou la gestion des comptes, ou le backup des bases par exemple.

Comment fonctionne l'accès aux données :

Voici le schéma classique (très simplifié) de l'accès aux données via ADO.net :

C'est le principe du schéma client/serveur classique. Un serveur de données peut accueillir plusieurs clients et traiter toutes leurs requêtes. Le serveur et les clients de données peuvent se trouver sur le même ordinateur, ADO.net comporte plusieurs espaces de noms comprenant des « Adapter » capable de se connecter aux principaux serveurs de données.

Cependant, nous ne travaillerons pas vraiment avec ce type de serveur pour notre application puisqu'il va s'agir d'une base locale. Nous aurons alors un substitut de serveur, SQL Serveur Compact Edition qui permettra une sorte de simulation du serveur, bien moins puissant qu'un vrai serveur de données mais largement suffisant pour notre application locale.

Ou se situe la différence ?

Avec SQL CE, vous ne pouvez pas consulter une base se trouvant sur un ordinateur distant.

SQL CE n'inclut pas de gestion de l'authentification, n'importe qui peut donc avoir accès à vos bases (depuis votre poste) si vous ne les cryptez pas.

Il faut spécifier l'emplacement de la base sur le disque dans la chaine de connexion.

Mais alors quel est l'avantage ?

Alors qu'une installation d'un serveur de données nécessite parfois l'achat d'une licence, l'installation et le paramétrage complexe de son instance, SQL CE s'installe comme un petit composant additionnel et prend très peu de place sur le poste client. SQL Serveur CE est conçu pour les applications mobiles, Smartphone et PDA.

Voila pour ces quelques précisions, mais je vous propose de suite d'en revenir à nos moutons et de découvrir les bases du langage SQL en quatre requêtes :

  • La requête SELECT qui permet d'obtenir les données de notre table, en lui précisant ou non certains paramètres de recherche,
  • La requête INSERT qui va permettre l'ajout de nouveaux enregistrements dans notre base de données,
  • La requête UPDATE pour mettre à jour les enregistrements de notre base,
  • La requête DELETE permettant de supprimer des enregistrements.

Figure 10, DataSet Fortement typé dans l'explorateur de solution de Visual Basic.

Bien entendu, pour envoyer ces requêtes à notre base, ou plutôt au serveur local de données, nous devrons saisir du code. Mais Visual studio possède comme pour l'éditeur de tables, d'autres assistants et éditeurs qui nous permettent d'automatiser cette tâche. C'est le cas du DataSet fortement typé, conçu pour nous faciliter la tâche quand à la communication avec notre serveur de données.

Comment cela fonctionne ?

Le DataSet fortement typé va nous permettre d'associer une ou plusieurs tables de notre base avec les quatre requêtes de base du langage SQL via un objet appelé le « TableAdapter ». En gros, il permet de créer une sorte de contrôle utilisateur contenant quatre méthodes en VB qui permettront la récupération, l'ajout, la suppression et la modification des données de notre base.

Pour comprendre, rien de mieux que la pratique, je vous invite donc à double-cliquer sur le DataSet fortement Typé dans votre explorateur de solution (Fig. 10), pour ouvrir celui-ci dans le concepteur de vue de Visual Basic (Fig. 11).

Figure 11, DataSet Fortement typé dans le concepteur de vue.

Votre DataSet doit donc apparaître sous la forme d'une fenêtre vide avec un fond laissant penser à du papier kraft, et quelques écrits en arrière plan. Effectué un clic avec le bouton droit de votre souris dans cet espace vide, puis dans le menu apparent, sélectionnez « Ajouter » et « TableAdapter ».

L'assistant de configuration de TableAdaper apparaissant (Fig. 11), cliquez sur suivant en prenant le soin de vérifier que le nom de la chaine de connexion corresponde bien à la base de données de notre projet.

Figure 11, Assistant de configuration de TableAdapter.

L'étape suivante (Fig. 12) nous interroge sur la façon dont le TableAdapter devra accéder à notre Table. Une base SQL CE ne permettant pas d'autre choix que le langage SQL via des requêtes directes nous passerons donc cette étape en cliquant à nouveau sur suivant.

Figure 12, Assistant de configuration de TableAdapter.

C'est à partir d'ici que notre TableAdapter va prendre une tournure plus intéressante. L'assistant nous demande de préciser quelles données devront être chargées dans la table. C'est à partir de ce code, qui devra être une requête select, permettant la récupération des données, que notre TableAdapter sera conçu, ainsi qu'un modèle de DataTable qui lui sera associé (voir Fig. 13).

Figure 13, Assistant de configuration de TableAdapter - Instruction SQL.

Nous pouvons à ce stade, saisir notre requête SELECT, en texte brut dans le champ présenté figure N° 13. Mais encore une fois, Visual Studio possède plus d'une corde à son arc, et nous permettra une saisie facilitée grâce à son « Générateur de requêtes SQL ». Cliquez alors sur le bouton Générateur de requête, pour voir apparaitre celui-ci (Fig. 14).

Figure 14, Le générateur de requêtes SQL de Visual Studio.

Une base pouvant posséder plusieurs tables, et un TableAdapter pouvant renvoyer des lignes issues des données de plusieurs tables, nous serons donc invités à préciser quelles tables feront partie de notre requête SELECT.

Notre projet ne possédant qu'une Table, nous ajouterons donc celle-ci, en la sélectionnant puis en l'ajoutant en cliquant sur les boutons respectifs.

Figure 15, Le générateur de requêtes SQL de Visual Studio - Table Contacts.

Notre table sélectionnée, elle nous apparait donc de façon visuelle (Fig. 15). Nous n'aurons qu'à cocher des cases dans la liste des colonnes disponibles depuis notre table pour que l'éditeur crée la requête SQL à notre place, nous évitant ainsi d'avoir la lourde tâche de la saisir par nous même. Pour notre projet, nous aurons besoin de récupérer tous les champs de notre table, nous cocherons donc la case astérisque « * », une sorte de joker précisant que nous souhaitons récupérer tous les champs.
Fermez le générateur en cliquant sur OK.

Figure 16, Assistant de configuration de TableAdapter - Instruction SQL.

Nous retrouvons donc notre assistant de configuration de TableAdapter, figure 16, dont la requête a été définie par notre générateur de requête. Vous pouvez maintenant passer à l'étape suivante.

Figure 17, Assistant de configuration de TableAdapter.

Figure 17 > L'assistant vous demande quelles types de méthodes vous souhaiter générer :

Remplir un DataTable : Cette méthode n'est rien d'autre qu'une routine (Sub) qui remplira une DataTable des données retournées par les requêtes SELECT.

Retourner un DataTable : même chose que pour la précédente, sauf que cette fois ci, il s'agit d'une fonction et non d'une routine, qui retourne un DataTable rempli.

Les deux méthodes ci-dessous ont exactement le même but, elles ne diffèrent que dans la stratégie que vous emploierez pour coder votre application. Je vous conseille donc de toujours laisser ces deux méthodes si vous ne maitrisez pas parfaitement le concept du TableAdapter.

La troisième option est comme qui dirait, « magique » car elle va nous éviter d'avoir à saisir les trois autres requêtes.

En effet, à ce stade, nous avons saisi la méthode SELECT, pour récupérer nos données, mais nous n'avons pas précisé les requêtes INSERT, UPDATE et DELETE, permettant de compléter les opérations nécessaires au bon fonctionnement de notre programme. L'assistant va donc déduire ces requêtes d'après les champs que nous avons sélectionnés à l'étape précédente lors de la création de notre requête SELECT.

Figure 18, Assistant de configuration de TableAdapter- Résultat.

Si tout s'est bien déroulé et qu'il n'y a pas d'erreur dans votre requête SELECT, vous devriez avoir le même résultat que présenté figure 18.

Comme je l'ai précisé plus haut, le TableAdapter est une représentation Graphique des requêtes SQL qui permettent de travailler avec des données. Il est associé à une DataTable. Figure19, vous devriez apercevoir dans le concepteur de vue de votre DataSet, le TableAdapter que nous venons de créer nommé « ContactsTableAdapter » par défaut, ainsi que sa Table associée sous le nom de « Contacts ».

Figure 19, TableAdapter et DataTable en mode design.

Pour finir cette automatisation du travail avec les données, il nous reste à modifier certains paramètres. Ce n'est pas obligatoire mais cela nous rendra le travail plus agréable. Tout à l'heure nous avons pu voir que les requêtes INSERT, UPDATE et DELETE de notre TableAdapter ont été générées dynamiquement par notre assistant. Cependant, celui-ci ne renomme parfois pas très bien les paramètres à passer à nos requêtes.

Figure 20, Propriétés du TableAdaper.

Cliquez sur l'entête de notre TableAdaper (Surligné en jaune Fig. 20) et regardez dans l'éditeur de propriétés de Visual Basic. Nous retrouvons nos quartes méthodes SQL. Pour commencer nous allons modifier la requête DELETE. Positionnez-vous sur l'étiquette « CommandText » de la propriété « DeleteCommand » de notre TableAdapter et cliquez sur le bouton parcourir « ... » (Fig. 21).

Figure 21, Propriétés du TableAdaper.

Figure 22, retour au générateur de requête. Voila l'une des fameuses requêtes générées automatiquement par l'assistant. Vous pouvez voir que les paramètres précédés d'un @ sont nommés P suivis d'un chiffre, ce qui ne facilite pas vraiment la compréhension sous l'éditeur de code de Visual basic.

Figure 22, Générateur de requêtes.

Pour la facilité, je renommerais donc tous les paramètres par leurs noms, une fois modifiée la requête ressemble à ceci :

Nous allons maintenant procéder de la même manière pour les deux requêtes restantes :

Figure 23, Propriétés du TableAdaper.

Figure 23, recommencez l'opération pour la requête INSERT.

Figure 24, Générateur de requêtes.

Remplacer les paramètres par leurs noms pour obtenir le code ci-dessous :

Note : Vous aurez remarqué que j'ai intentionnellement supprimé le paramètre ID, souvenez vous que lors de la construction de notre base, nous avons défini la valeur par défaut de cette colonne à newid(), il n'est donc pas nécessaire de préciser ce paramètre, le moteur de base de données SQL CE s'en chargera pour nous.

Puis pour la requête DELETE :

Figure 25, Propriétés du TableAdaper.

Figure 26, Générateur de requêtes.

En modifiant le code pour obtenir ceci :

Nous venons de terminer une étape importante, puis ce qu'à ce stade, notre programme est capable de :

  • Interroger la base de données,
  • Ajouter des enregistrements dans la table « Contacts » de notre base,
  • Supprimer des lignes de la table « Contacts »,
  • Modifier des enregistrements dans la table « Contacts ».

Je vous rappelle que jusqu'ici, même si ce tutoriel parait interminable (ah bon..? Pas pour vous ?!) , vous n'avez eu besoin de solliciter votre clavier qu'un nombre très limité de fois.

Le code behind et l'interface

A ce stade nous n'aurions besoin que de saisir quelques lignes de code en VB pour rendre fonctionnelle notre Interface.

Cependant, le but de ce tuto est aussi de démontrer comment tirer profit de Visual basic et de ses assistants, afin de vous permettre d'être le plus productif possible.

Cependant, je tiens à vous montrer comment manipuler les objets que nous avons précédemment créés par code, afin que vous puissiez avoir un aperçu de ce que nous allons faire via les assistants de Visual studio.

Voici comment, exploiter les quatre méthodes de notre TableAdapter par code behind.

Tout d'abord, voici la procédure permettant de récupérer les données de notre table contacts :

'
'Création d'une instance de notre TableAdapter.
Dim MonTableAdapter As New MonDataSetTableAdapters.ContactsTableAdapter

'Création d'une instance de notre table associé.
Dim MaDataTable As New MonDataSet.ContactsDataTable

'Appel de la méthode GetData de notre instance de TableAdapter pour le
'remplissage de la table.
MaDataTable = MonTableAdapter.GetData

Nous obtenons donc un objet MaDataTable, qui contient des lignes et des champs, avec les données de notre table, nous pouvons exploiter les données contenues par cet objet pour les afficher dans notre interface.

Pour l'ajout de nouveaux enregistrements :

'
'Création d'une instance de notre TableAdapter.
Dim MonTableAdapter As New MonDataSetTableAdapters.ContactsTableAdapter

'Appel de la méthode Insert de notre TableAdapter en passant en paramètres
'toutes les données à insérer.
MonTableAdapter.Insert("DUPONT", _
"Jean", _
25, _
"2 Rue du pré", _
"75000", _
"Paris", _
"France", _
"01 32 00 00 00", _
"", _
"", _
"dupontj@domaine.com", _
"")

Note : Tout à l'heure, nous avons modifié les requêtes générées automatiquement par Visual studio. Dans la capture ci-dessous, vous pouvez voir que cela s'avère très utile, car, dans l'info bulle qui s'affiche lors de la saisie de notre procédure, ce sont bien les noms des champs que nous avons et non des champs nommés p1, p2, p3...

Poursuivons avec la méthode Update. Ici, nous repassons l'instance à notre TableAdapter pour qu'il mette à jour notre table dans la base. Nous supposons que celle-ci a été modifiée entre temps. Mais la méthode Update générée automatiquement présente l'avantage d'avoir plusieurs surcharges. Ainsi nous pouvons lui passer, en référence, l'instance de notre table, mais également un DataSet ou simplement une ligne de table. Elle permet également de définir les champs manuellement tels que le fait la méthode Insert ci-dessus.

'
'Création d'une instance de notre TableAdapter.
Dim MonTableAdapter As New MonDataSetTableAdapters.ContactsTableAdapter

'Appel de la méthode Insert de notre TableAdapter en passant 
'en paramètre toutes les données à insérer.
MonTableAdapter.Update(MaDataTable)

Pour finir regardons du coté de la méthode Delete, ici, le seul paramètre que nous devrons passer en référence est l'ID de la ligne à supprimer.

'
'Création d'une instance de notre TableAdapter.
Dim MonTableAdapter As New MonDataSetTableAdapters.ContactsTableAdapter

'Appel de la méthode Insert de notre TableAdapter en passant en paramètre
'toutes les données à insérer.
MonTableAdapter.Delete(ID)

Voila le résumé en quelques lignes de code, de la manipulation d'une table après avoir configuré notre DataSet correctement.

Mais passons donc à la construction de notre interface graphique.

Commencez par ajouter un composant BindingNavigator

Figure 27.

Renommez celui-ci : « Navigator »

Puis ajoutez un SplitContainer :

Figure 28.

Dans la partie gauche du SplitContainer, placez-y un DataGridView.

Figure 29.

Renommez celui-ci « DGV », puis ancrez le dans le conteneur parent. Définissez sa propriété « MultiSelect » sur « False » et sa propriété « SelectionMode » sur « FullRowSelect ».

Placez en suite dans la partie gauche du SplitContainer, un GroupBox

Figure 30.

Modifiez la propriété « Text » de celui-ci pour « Propriétés du contact ». Puis définissez la propriété « Anchor » au quatre cotés Top, Left, Right, Bottom.

Placez dans ce GroupBox, un contrôle Panel

Figure 31.

Et définissez sa propriété Dock sur Fill, Sa propriété AutoScroll sur True ainsi que sa propriété AutoScrollMagin sur (5 ; 5).

Pour le reste, ajoutez des contrôles TextBox pour chaque champ de notre table contact, excepté pour le champ « Age » ou vous dessinerez un NumericUpDown et le champ ID ou vous ne mettrez rien. Pour chaque contrôle TextBox vous modifierez les propriétés suivantes :

  • MaxLength : mettez la valeur de la longueur du champ correspondant (ex : 255 pour nom), pour le NumericUpDown mettez sur 150 la propriété Max,
  • Mutliligne : Mettez sur True pour commentaire et Adresse,
  • Nom, renommez les contrôles avec le préfix « txt_ » suivis du nom du champ et « nud_ » pour le NumericUpDown (ex : « txt_Nom »),

Créez des étiquettes avec des labels et vous devriez avoir un design ressemblant à ceci :

Figure 32.

Placez également sur votre formulaire un ErrorProvider que vous nommerez « EP »

Notre interface prête nous allons commencer à la faire interagir avec notre DataSet.

Nous allons nous occuper dans un premier temps du DataGridView.
Cliquez sur le DataGridView pour ouvrir son smart Tag (petite flèche en haut à droite).
Puis déroulez la liste de choix de source de données, développez les sources de données du projet jusqu'à arriver à notre table « Contacts ».
Sélectionnez celle-ci.

Figure 33.

Ceci fait, le DataGridView génère automatiquement des colonnes, vous pouvez aussi voir que des contrôles sont apparus en bas de votre formulaire (à côté du BindingNavigator et de l'ErrorProvider) ce sont les instances de nos composants créés à l'aide de notre DataSet fortement typé.

Figure 34.

Décochez les cases du smart tag permettant l'ajout, la modification et la suppression de données, et activez celle permettant la réorganisation des colonnes si vous le souhaitez. Cliquez en suite sur le lien « Modifier les colonnes », nous allons supprimer certaines colonnes dont l'affichage ne servira pas vraiment.

Supprimez toutes les colonnes sauf :

  • ID
  • Nom
  • Prenom
  • Ville

Définissez la propriété « Visible » de la colonne « ID » sur « False », nous ne supprimerons pas cette colonne car nous aurons besoin de cette information, ce pendant il est inutile d'afficher celle-ci à l'écran, car elle doit être transparente pour l'utilisateur. Vous devriez donc avoir le schéma de colonne suivant :

Figure 35.

Que venons-nous de faire ?

Je vous ai démontré plus haut, que l'appel des méthodes de notre TableAdapter se fait en quelques lignes de code, celle-ci doivent d'abord passer par l'étape de l'instanciation de notre TableAdapter, souvenez-vous :

'
'Création d'une instance de notre TableAdapter.
Dim MonTableAdapter As New MonDataSetTableAdapters.ContactsTableAdapter

En précisant la source de données à notre DataGridView, celui-ci a généré un composant sur le formulaire, qui n'est autre qu'une instance de notre TableAdapter « ContactsTableAdapter », cette instance porte le même nom :

Figure 36.

Elle correspond en fait, à la ligne de code que nous aurions du saisir :

'
Dim ContactsTableAdapter As New MonDataSetTableAdapters.ContactsTableAdapter

Il en va de même pour l'instance de notre Table,

'
'Création d'une instance de notre table associée.
Dim MaDataTable As New MonDataSet.ContactsDataTable

Celle-ci apparait aussi en tant que contrôle figure 36. Cette instance de notre table est donc reliée à la propriété DataSource de notre contrôle DataGridView. Chaque fois que cette DataTable sera modifié, le contenu de note DataGridView le sera également. Et si nous regardons de plus près ce qui se passe dans le code behind de notre formulaire, nous pouvons voir ceci :

'
Public Class Form1

Private Sub Form1_Load(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles MyBase.Load

'TODO : cette ligne de code charge les données dans la table
'MonDataSet.Contacts'. Vous pouvez la déplacer ou la supprimer selon vos besoins.

Me.ContactsTableAdapter.Fill(Me.MonDataSet.Contacts)

End Sub

End Class

L'EDI a créé une ligne de code permettant le remplissage de notre table au moment du chargement de notre formulaire.

Que va-t-il donc se passer ?

Lors du chargement, ContactsTableAdapter va exécuter notre requête SELECT et remplir notre instance de DataTable Contacts, celle-ci étant relié au DataGridView, lui signalera que son contenu vient de changer et il se mettra à jour automatiquement. Pour résumer, nous aurons donc l'affichage de tous les contacts de notre table au chargement de l'application.

Bien entendu, ce que nous venons de faire par assistant, nous pouvons aussi le faire par code, nous aurions du alors saisir nous même dans notre formulaire :

'
Public Class Form1

Private Sub Form1_Load(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles MyBase.Load

'Création d'une instance de notre TableAdapter.
Dim MonTableAdapter As New MonDataSetTableAdapters.ContactsTableAdapter

'Création d'une instance de notre table associé.
Dim MaDataTable As New MonDataSet.ContactsDataTable

'Appel de la méthode GetData de notre instance de TableAdapter pour le
'remplissage de la table.
MaDataTable = MonTableAdapter.GetData

'Association de la DataTable et du DataGridView
DGV.DataSource = MaDataTable

End Sub

End Class

J'espère qu'arrivé ici, vous avez réussi à saisir le concept, j'essaye d'être le plus clair possible, bien que ce ne soit pas évident.

Reprenons notre figure 36, en la regardant attentivement, on peut y voir un autre contrôle, de type BindingSource, ce contrôle est nommé « ContactBindingSource ». Il a également été généré au passage, mais à quoi sert-il ?

Un BindingSource est un contrôle servant d'intermédiaire entre une source de données (Tel qu'une DataTable) et un ou plusieurs contrôles de données. Il permet synchroniser la navigation entre les contrôles au sein de cette source de données mais plus encore, il permet d'appliquer un filtre pour la recherche dans une table sans avoir renvoyer une requête au serveur, ce qui permet un filtrage rapide.

En résumé, lorsque l'on définit une liaison aux données d'un composant de données en Visual basic :

  • Une instance de TableAdapter est créée en tant que contrôle visuel,
  • Une instance de DataTable es t créée en tant que contrôle visuel,
  • Une instance de BindingSource est créée en tant que contrôle visuel,
  • Le TableAdapter rempli le DataTable au démarrage,
  • Le BindingSource a pour source de données ce DataTable,
  • Et enfin le contrôle a pour source de données le BindingSource.

Si des instances de BindingSource, TableAdapter, et DataTable sont déjà créés, vous pourrez directement choisir ceux-ci.

La gestion de notre DataGridView étant terminée, nous passerons maintenant à la gestion de nos contrôles de droite, les champs présents dans le Panel. De même que pour notre DataGridView, nous allons lier ces champs à notre source de données.

Je vous invite donc à cliquer sur le premier élément de ce panel qui n'est autre que le TextBox « txt_Nom ».

Figure 37.

Développer la propriété DataBindings du contrôle, positionnez-vous sur « (Avancées) » puis cliquez sur le bouton parcourir « ... »

Figure 38 - Liaison de contrôles aux données.

Dans le champ « Liaison », recherchez le champ « Nom » de notre « ContactBindingSource » et sélectionnez celui-ci, positionnez le champ « Mode de mise à jour de la source de données » sur « Never ». En effet, nous mettrons la source de données à jour par code, lors ce que nous cliquerons sur un bouton pour enregistrer le contact et non lors du changement dans un champ.

Figure 39 - Liaison de contrôles aux données.

Vous devez recommencer l'opération pour tous les contrôles présents dans notre Panel, en prenant soin de sélectionner le champ correspondant.

Que venons-nous de faire ?

Nous avons pu voir que le contrôle BindingSource est en fait une source de données tenant lui-même sa source d'une autre source de données. Il est un intermédiaire. En liant nos contrôles à ce BindingSource, les champs se rempliront automatiquement, chaque fois que la ligne sélectionnée dans le DataGridView changera.

Nous allons passer à la dernière étape. Cette étape permettra de finaliser notre programme, de le rendre fonctionnel.

Pour commencer nous allons définir la propriété « BindingSource » de notre contrôle « Navigator » sur « ContactBindingSource » ce qui rendra fonctionnel la navigation dans notre source de données.

Figure 40 - Propriétés de « Navigator ».

Puis nous allons finaliser notre interface en supprimant les deux boutons par défaut créés par notre BindingNavigator, pour les remplacer par 3 nouveaux dont les noms seront respectivement « btn_Save », « btn_Del » et « btn_New », vous pouvez définir la propriété « DisplayStyle » sur « ImageAndText » et saisir les étiquettes des bouton puis leur ajouter des icônes comme je l'ai fait figure 42.

Figure 41 - Suppression des boutons par défaut du BindingNavigator.

Figure 42 - Ajout de nouveaux boutons.

Définissez la propriété « Enabled » des contrôles « btn_Save » et « btn_Del » sur « False » (Fig. 42). Ajoutez un séparateur, un TextBox et ComboBox, nommés « txt_SearchArgs » et « cbo_Filter » et deux labels servant d'étiquettes afin de définir un champ de recherche voir figure 43 ci-dessous.

Figure 43 - Champ de recherche.

Définissez la propriété « DropDownStyle » du ComboBox sur « DropDownList », et remplissez sa propriété « Items » par les éléments suivants :

Figure 44 - éléments du ComboBox.

Vous l'aurez compris, il s'agit des champs de notre table, pour lesquels nous allons appliquer un filtre de recherche.

Le reste de notre application, se déroulera dans la partie code behind de notre formulaire.
Ouvrez le code behind de celui-ci, vous devriez avoir le code ci-dessous :

'
Public Class Form1

Private Sub Form1_Load(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles MyBase.Load

'TODO : cette ligne de code charge les données dans la table
'MonDataSet.Contacts'. Vous pouvez la déplacer ou la supprimer selon vos besoins.

Me.ContactsTableAdapter.Fill(Me.MonDataSet.Contacts)

End Sub

End Class

Nous allons quelque peu modifier le code généré par l'EDI afin de pouvoir faciliter l'appel de celui-ci dans d'autres procédures que celle du chargement de notre formulaire.

'
'Procédure "Load" de notre formulaire qui se déclenche au chargement de celui-ci.
Private Sub Form1_Load(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles MyBase.Load
'
cbo_Filter.SelectedIndex = 0
Call RefreshDataSource()
'
End Sub
'
'Procédure privée permettant le remplissage de notre source de données
'avec les éléments contenus dans notre base.
Private Sub RefreshDataSource()
'
'Remplissage de l'instance de notre DataTable "Contacts" par l'instance
'de Notre TableAdapter "ContactTableAdapter".
'Celui-ci exécute la requête SELECT pour remplir notre table des données
'que contient notre base physique "MaBaseLoacle.sdf".
Me.ContactsTableAdapter.Fill(Me.MonDataSet.Contacts)
'
End Sub

Pour éviter les erreurs potentielles, nous allons mettre à jour l'état de nos boutons du « Navigator », lors de la mise à jour de notre DataGridView.

'
'Procédure "DataBindingComplete" qui se déclanche une fois le DataGridView mis à jour.
Private Sub DGV_DataBindingComplete(ByVal sender As Object, _
ByVal e As System.Windows.Forms.DataGridViewBindingCompleteEventArgs) _
Handles DGV.DataBindingComplete
'
'Mise à jour de l'état des contrôles pour éviter les erreurs d'enregistrement
'et de suppression si le DataGridView ne contient aucune ligne.
btn_Del.Enabled = (DGV.RowCount <> 0)
btn_Save.Enabled = (DGV.RowCount <> 0)
'
End Sub

Puis interviendra le code de nos boutons, permettant d'ajouter, de modifier ou de supprimer des contacts dans notre table tout en prenant soin de prévenir des erreurs éventuelles.

'
'Procédure "Click" de notre bouton de sauvegarde des contacts.
Private Sub btn_Save_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles btn_Save.Click
'
'Gestion des erreurs de saisie
'
Dim HasError As Boolean = False
EP.Clear()
'
If txt_Nom.Text.Length = 0 Then
    EP.SetError(txt_Nom, "Le champ ""Nom"" ne peut être vide !")
    HasError = True
End If
'
If txt_Prenom.Text.Length = 0 Then
    EP.SetError(txt_Prenom, "Le champ ""Prénom"" ne peut être vide !")
    HasError = True
End If
'
If HasError Then
    Exit Sub
End If
'
REM: nous pourrions aller plus loin dans cette gestion des erreur
REM: avec l'ajout d'expressions régilères (RegEx)
REM: pour contrôler les champs tel que l'email ou le code postal,
REM: mais ce n'est pas le but de ce tutoriel.
'
'Récupération de la valeur de la colonne 0 de la première ligne
'sélectionné dans notre DGV.
Dim ID As Guid = CType(DGV.SelectedRows(0).Cells(0).Value, Guid)
'
Try
'
'Appel de la procédure Update de notre TableAdapter qui tranmettra
'la requête SQL UPDATE.
    Dim NbLine As Integer = ContactsTableAdapter.Update(txt_Nom.Text, _
    txt_Prenom.Text, _
    CShort(nud_Age.Value), _
    txt_Adresse.Text, _
    txt_CP.Text, _
    txt_Ville.Text, _
    txt_Pays.Text, _
    txt_Tel.Text, _
    txt_Mobile.Text, _
    txt_Fax.Text, _
    txt_Email.Text, _
    txt_Commentaire.Text, _
    ID)
REM: Cette procédure retourne un entier indiquant le nombre de lignes modifiés.
'
    If NbLine > 0 Then
'
        MessageBox.Show("Le contact a bien été mis" & _
        " à jour dans la base de données.", _
        "Mise à jour du contact", _
        MessageBoxButtons.OK, _
        MessageBoxIcon.Information)
'La modification effectuée nous actualisons les données de notre source
'de données en effectuant une requête
'SELECT de nouveau.
        Call RefreshDataSource()
    End If
'
    Catch ex As Exception
'
        MessageBox.Show("Une erreur est survenue durant l'accès" & _
        " à la base de données." & Environment.NewLine & _
        "Détails de l'erreur: " & ex.Message, _
        "Echec de l'accès aux données.", _
        MessageBoxButtons.OK, _
        MessageBoxIcon.Exclamation)
'
End Try
'
End Sub
'
'Procédure "Click" de notre bouton de suppression des contacts.
Private Sub btn_Del_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles btn_Del.Click
'
'Validation de la demande de suppression
Dim result As DialogResult = MessageBox.Show("Voulez-vous vraiment supprimer ce" & _
" contact ?", _
"Suppression définitive ?", _
MessageBoxButtons.YesNo, _
MessageBoxIcon.Question)
'
'Si la réponse est autre que Oui, alors on quitte la procédure
If result <> Windows.Forms.DialogResult.Yes Then
    Exit Sub
End If
'
'Récupération de la valeur de la colonne 0 de la première ligne
'sélectionné dans notre DGV.
Dim ID As Guid = CType(DGV.SelectedRows(0).Cells(0).Value, Guid)
REM: Cette procédure retourne un entier indiquant le nombre de lignes modifiés.
'
Try
'
'Appel de la procédure DELETE, de notre TableAdapter qui transmettra la
'requête SQL DELETE.
    Dim NbLine As Integer = ContactsTableAdapter.Delete(ID)
    REM: Cette procédure retourne un entier indiquant le nombre de lignes modifiés.
'
    If NbLine > 0 Then
'
        MessageBox.Show("Le contact a bien été supprimé de la base de données.", _
         "Suppression du contact", _
        MessageBoxButtons.OK, _
        MessageBoxIcon.Information)
'La suppression effectuée nous actualisons les données de notre source
'de données en effectuant une requête SELECT de nouveau.
        Call RefreshDataSource()
    End If
'
    Catch ex As Exception
'
    MessageBox.Show("Une erreur est survenue durant l'accès à la base de données." & _
    Environment.NewLine & _
    "Détails de l'erreur: " & ex.Message, _
    "Echec de l'accès aux données.", _
    MessageBoxButtons.OK, _
    MessageBoxIcon.Exclamation)
'
End Try
'
End Sub
'
'Procédure "Click" de notre bouton d'ajout de contacts.
Private Sub btn_New_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles btn_New.Click
'
'Gestion des erreurs de saisie
'
Dim HasError As Boolean = False
EP.Clear()
'
If txt_Nom.Text.Length = 0 Then
    EP.SetError(txt_Nom, "Le champ ""Nom"" ne peut être vide !")
    HasError = True
End If
'
If txt_Prenom.Text.Length = 0 Then
    EP.SetError(txt_Prenom, "Le champ ""Prénom"" ne peut être vide !")
    HasError = True
End If
'
If HasError Then
    Exit Sub
End If
'
REM: nous pourrions aller plus loin dans cette gestion des erreur avec
REM: l'ajout d'expressions régilères (RegEx)
REM: pour contrôler les champs tel que l'email ou le code postal,
REM: mais ce n'est pas le but de ce tutoriel.
'
Try
'
'Appel de la procédure Insert de notre TableAdapter,
'qui transmettra la requête SQL INSERT.
    Dim NbLine As Integer = ContactsTableAdapter.Insert(txt_Nom.Text, _
    txt_Prenom.Text, _
    CShort(nud_Age.Value), _
    txt_Adresse.Text, _
    txt_CP.Text, _
    txt_Ville.Text, _
    txt_Pays.Text, _
    txt_Tel.Text, _
    txt_Mobile.Text, _
    txt_Fax.Text, _
    txt_Email.Text, _
    txt_Commentaire.Text)
REM: Cette procédure retourne un entier indiquant le nombre de lignes modifiés.
'
    If NbLine > 0 Then
'
        MessageBox.Show("Le contact a bien été ajouté à la base de données.", _
        "Ajout du contact", _
        MessageBoxButtons.OK, _
        MessageBoxIcon.Information)
'
'L'ajout effectué nous actualisons les données de notre source
'de données en effectuant une requête SELECT de nouveau.
        Call RefreshDataSource()
'
    End If
'
    Catch ex As Exception
'
    MessageBox.Show("Une erreur est survenue durant l'accès à la base de données." & _
    Environment.NewLine & _
    "Détails de l'erreur: " & ex.Message, _
    "Echec de l'accès aux données.", _
    MessageBoxButtons.OK, _
    MessageBoxIcon.Exclamation)
'
End Try
End Sub

Jusqu'ici, notre programme est entièrement fonctionnel quant à l'accès aux données.Ce qu'il nous reste à faire c'est de saisir le code qui permettra au moteur de recherche de fonctionner. Ce code doit agir lors ce que l'on saisit du texte dans notre champ de recherche, ou lors ce que l'on détermine quel champ va-t-être la cible de notre recherche.

'
'Procédure privée, se déclanchant lors des événements "TextChanged" de notre contrôle
'"txt_SearchArgs" et "SelectedIndexChanged" de notre contrôle "cbo_Filter"
Private Sub Filter_Change() Handles txt_SearchArgs.TextChanged, _
cbo_Filter.SelectedIndexChanged
'
'Nous allons changer la propriété "Filter" de notre BindingSource
Dim FilterArgs As String = cbo_Filter.Text & " LIKE '" & txt_SearchArgs.Text & "%'"
'
REM: la propriété "Filter" du BindingSource fonctionne comme
REM: une clause "WHERE" en SQL. Nous utilisons la clause "LIKE"
REM : et le joker "%" pour préciser que le champ commence par le texte
REM: saisi dans le TextBox "txt_SearchArgs.
'
'Application du filtre
ContactsBindingSource.Filter = FilterArgs
'
End Sub

Et voila, notre programme est entièrement fonctionnel et prêt à être distribué.

Déploiement de notre projet

Nous allons voir dans ce chapitre (eh oui, je parle maintenant de chapitre car je ne pensais pas avoir autant de pages à écrire pour un si petit projet) comment déployer notre application afin de pouvoir l'installer sur une plateforme autre que celle dont nous nous servons pour le développement.

Je vais donc vous inviter à ouvrir les propriétés de notre projet en double cliquant sur l'icône MyProject dans l'explorateur de solutions de Visual Basic.

Figure 45 - Explorateur de solutions.

Figure 46 - Propriétés du projet, onglet « Publier ».

Allez à l'onglet « Publier » comme le montre la figure 46, puis cliquez sur le bouton « Composants requis »

Figure 47 - Composants redistribuables.

Vérifiez que le composant redistribuable « SQL Server Compact 3.5 » soit coché puis fermez cette fenêtre et les propriétés de votre projet. Toujours dans l'explorateur de solution, faites un clic avec le bouton droit de votre souris sur l'icône de votre projet (ici MyLocalDataApp) et sélectionnez « Publier » dans le menu qui s'affiche.

Suivez les étapes des figures suivantes, en laissant par défaut tous les paramètres.

Figure 48 - Emplacement de la publication.

Figure 49 - Mode de publication.

Figure 50 - Options de mise à jour.

Figure 51 - Récapitulatif avant publication.

Conclusion

Vous savez maintenant avec quelle facilité il est possible de réaliser des applications de données en .Net via Visual Studio. Ce tutoriel est assez long car j'ai tenu à rentrer dans les détails au maximum, mais pour quelqu'un qui maitrise les outils de Visual Studio, il ne faudra pas plus d'une dizaine de minutes pour venir à bout d'une application comme celle-ci.

Nous avons travaillé avec des données en local, mais les outils dont je vous ai fait la démonstration fonctionnent aussi pour la gestion des données en général. Il est donc possible d'employer ces méthode pour un logiciel de base de données traitant avec un autre SGBD, qu'il soit local ou distant (Base Access, Excel, SQL Serveur, MySQL, Oracle...).

Voila, ce tutoriel touche à sa fin, en espérant que j'aurais été assez clair pour permettre d'en apprendre plus sur la gestion des données en Visual Basic.

Mayzz.

A voir également
Ce document intitulé « Gestion des données visual basic 2008 et sql server ce » issu de CodeS SourceS (codes-sources.commentcamarche.net) est mis à disposition sous les termes de la licence Creative Commons. Vous pouvez copier, modifier des copies de cette page, dans les conditions fixées par la licence, tant que cette note apparaît clairement.
Rejoignez-nous