Cours VB.NETDate de mise à jour : 05/12/2010
XVII-D. ADO:Lire rapidement en lecture seule: le DataReader
XVII-D-1. Généralités
XVII-D-2. Exemple de DataReader avec une base Access
XVII-D-3. Comment compter ?
XVII-D-4. L'objet Connection (détails)
XVII-D-5 . L'objet Command (détails)
XVII-D-6. L'objet DataReader (détails)
XVII-D-7. Exceptions
XVII-E. ADO: Travailler sur un groupe de données: le DataSet
XVII-E-1. Généralités
XVII-E-2. Utilisation du DataSet, du DataView: en pratique
XVII-E-3. Remplir un DataGrid ou une ListBox avec un DataSet
XVII-E-4. Étudions en détail un DataSet
XVII-F. Liaison DataGrid, ListBox et base de données: le "DataBinding"
XVII-F-1. Remplir une ListBox avec une colonne d'une table d'une BD
XVII-F-2. Remplir un DataGrid avec une base de données via un DataSet.
XVII-F-3. Remplir un contrôle avec une source de données avec le moins de code possible(VB 2005 2008).
XVII-F-3-a. Création de la source de données
XVII-F-3-b. Liaison source de données-Grid avec du code.
XVII-F-3-c. Génération automatique de l'interface utilisateur
XVII-F-3-d. Binding et TextBox
XVII-D. ADO:Lire rapidement en lecture seule: le DataReader
Comment lire rapidement des enregistrements? Avec un DataReader.
Comment compter les enregistrements? Avec ExecuteScalar
Etudions en détail les objets Connexion, Command, DataReader.
Et s'il y a une erreur ?
XVII-D-1. Généralités
Un objet DataReader fournit des données en lecture seule en un temps record. La seule possibilité est de se déplacer en avant.
En contrepartie de sa rapidité il monopolise la connexion.
Il faut créer un objet Connexion puis un objet Command, ensuite on exécute la propriété ExecuteReader pour créer l'objet DataReader; enfin on parcourt les enregistrements avec la méthode Read.
XVII-D-2. Exemple de DataReader avec une base Access
Il existe une base Access nommée 'consultation.mdb', elle contient une table 'QUESTIONS', dans cette table existe un champ 'NOM', je veux récupérer tous les noms et les afficher rapidement dans une ListBox.
Il faut importer les NameSpaces nécessaires.
Imports System. Data
Imports System. Data . OleDb
|
Il faut créer un objet connexion:
Dim MyConnexion As OleDbConnection = New OleDbConnection (" Provider=Microsoft.Jet.OLEDB.4.0;Data source= " & _
" C:\consultation.mdb " )
|
Il faut donner les paramètres Provider= et Data source=
Dans le cas d'une base Access le provider (le moteur à utiliser est le moteur OLEDB Jet 4.
Il faut créer un objet Command:
Dim Mycommand As OleDbCommand = MyConnexion. CreateCommand ()
|
Il faut donner dans la propriété CommandText la requête SQL permettant d'extraire ce que l'on désire.
Mycommand. CommandText = " SELECT NOM FROM QUESTIONS "
|
Ici dans la table QUESTIONS, on extrait le champ NOM
Il faut ouvrir la connexion:
Il faut créer un objet DataReader:
Dim myReader As OleDbDataReader = Mycommand. ExecuteReader ()
|
On crée une boucle permettant de lire les enregistrements les uns après les autres, on récupère le champ (0) qui est une String, on la met dans la ListBox
Do While myReader. Read ()
ListBox1. Items . Add (myReader. GetString (0 ))
Loop
|
Remarquons que le champ récupéré est typé (ici une string grâce à GetString); il y a d'autres types: GetDateTime, GetDouble, GetGuid, GetInt32, GetBoolean, GetChar, GetFloat, GetByte, GetDecimal etc..; il est possible de récupérer sans typage: on aurait écrit myReader(0) ou utiliser GetValue (on récupère un objet).
Read avance la lecture des données à l'enregistrement suivant , il retourne True s'il y a encore des enregistrements et False quand il est en fin de fichier; cela est utilisé pour sortir de la boucle Do Loop.
On ferme pour ne pas monopoliser.
myReader. Close ()
MyConnexion. Close ()
|
On aurait pu libérer la connexion automatiquement dès la lecture terminée en ajoutant un argument:
Dim myReader As OleDbDataReader = Mycommand. ExecuteReader (CommandBehavior. CloseConnection )
|
Simple, non!! (Je rigole!!)
Cela donne:
Imports System
Imports System. Data
Imports System. Data . OleDb
Imports Microsoft. VisualBasic
Public Class Form1
Inherits System. Windows . Forms . Form
Private Sub Form1_Load (ByVal sender As System. Object , ByVal e As System. EventArgs ) Handles MyBase. Load
Dim MyConnexion As OleDbConnection = New OleDbConnection (" Provider=Microsoft.Jet.OLEDB.4.0;Data source= " & _
" C:\consultation.mdb " )
Dim Mycommand As OleDbCommand = MyConnexion. CreateCommand ()
Mycommand. CommandText = " SELECT NOM FROM QUESTIONS "
MyConnexion. Open ()
Dim myReader As OleDbDataReader = Mycommand. ExecuteReader ()
Do While myReader. Read ()
ListBox1. Items . Add (myReader. GetString (0 ))
Loop
myReader. Close ()
MyConnexion. Close ()
End Sub
End Class
|
Dans le cas d'une base SQLSERVEUR, on aurait les changements suivant:
Imports System. Data . SqlClient
Dim MyConnexion As SqlConnection = New SqlConnection (" Data Source=localhost; " & _
" Integrated Security=SSPI;Initial Catalog=northwind " )
Dim Mycommand As SqlCommand = MyConnexion. CreateCommand ()
Dim myReader As SqlDataReader = Mycommand. ExecuteReader ()
|
XVII-D-3. Comment compter ?
Avec ExecuteScalar de l'objet Command on peut récupérer les résultats d'une requête Sql qui contient une instruction COUNT (comptage) AVG (moyenne) MIN (valeur minimum) MAX (valeur maximum) SUM (somme)
Exemple: compter le nombre de questions:
Mycommand. CommandText = " SELECT COUNT(*) FROM QUESTIONS "
MyConnexion. Open ()
Dim iResultat As Integer = Mycommand. ExecuteScalar ()
|
Voyons en détails les objets utilisés:
XVII-D-4. L'objet Connection (détails)
Il permet de définir une connexion.
Il faut donner les paramètres 'Provider='indiquant le moteur de BD et 'Data source=' indiquant le chemin et le nom de la BD. Il peut être nécessaire de donner aussi 'Password=' le mot de passe , 'User ID=' Admin pour l'administrateur par exemple.
Il faut mettre ces paramètres avec le constructeur, ou dans la propriété ConnectionString.
Dans le cas d'une base Access le provider (le moteur à utiliser) est le moteur OLEDB Jet 4.
Il y a d'autres propriétés:
State état de la connexion (Open, Close, Connecting, Executing, Fetching, Broken)
Open, Close
ConnectionTimeOut,
BeginTransaction,
..
XVII-D-5 . L'objet Command (détails)
Pour chaque provider il y a un objet Command spécifique:
SqlCommand, OleDbCommand, mais tous les objets 'Command' on la même interface, les mêmes membres.
CommandType indique comment doit être traité la commande CommandText:
- Text ; par défaut (exécution direct des instructions SQL contenues dans CommandText)
- StoredProcedure: exécution de procédure stockée dont le nom est dans CommandText.
- Tabledirect?
Command permet de définir la commande à exécuter: SELECT UPDATE, INSERT, DELETE. en utilisant le membre CommandText
(Seul SELECT retourne des données)
CommandTimeOut indique la durée en secondes avant qu'une requête qui plante soit abandonnée.
ExecuteReader exécute le code SQL de CommandText et retourne un DataReader.
ExecuteScalar fait de même mais retourne la première colonne de la première ligne.
ExecuteNoQuery exécute le code SQL de CommandText (généralement une mise à jour par UPDATE, INSERT, DELETE ou un ajout de table) sans retourner de données.
XVII-D-6. L'objet DataReader (détails)
Pour chaque provider il y a un objet 'DataReader' spécifique:
SqlDatReader, OleDbDataReader
On a vu le membre Read qui avance la lecture des données à l'enregistrement suivant , il retourne True s'il y a encore des enregistrements et False quand il est en fin de fichier.
On a vu GetDateTime, GetDouble, GetGuid, GetInt32, GetBoolean, GetChar, GetFloat, GetByte, GetDecimal permettant de récupérer les valeurs typées des champs.
Il a bien d'autres propriétés:
GetName retourne le nom du champ (numéro du champ en paramètre)
GetOrdinal fait l'inverse: retourne le numéro du champ (nom en paramètre)
FieldCount retourne le nombre de colonne.
GetDataTypeName retourne le nom du type de donnés.
IsDBNull retourne True si le champ est vide
......
XVII-D-7. Exceptions
Chaque SGDB a des erreurs spécifiques. Pour les détecter il faut utiliser les types d'erreur spécifiques: SqlException et OleDbException par exemple:
Exemple d'interception d'erreur:
Try
MyConnection. Open ()
Catch ex As OleDbException
MsgBox (ex. Message )
End Try
|
XVII-E. ADO: Travailler sur un groupe de données: le DataSet
Comment travailler (lire écrire, modifier, trier..) sur des enregistrements d'une base de données ?
Avec un DataSet.
XVII-E-1. Généralités
Le DataSet est une représentation en mémoire des données. On charge le DataSet à partir de la base de données. Une fois chargé on peut travailler en mode déconnecté. Pour effectuer une modification, on modifie le DataSet puis on met à jour la base de donnée à partir du DataSet.
Pour remplir un DataSet il faut une Connexion puis un DataAdapter.
Il faut créer un objet Connexion puis un objet DataAdapter qui par sa propriété Fill charge le DataSet.
Les données sont extraites à l'aide de requête SQL sur l'objet Command, et on utilise un CommandBluider pour mettre à jour la base de donnée à partir du DataSet.
Le DataSet est organisé comme une base de données en mémoire, il possède:
- Une propriété Tables qui contient des DataTable (Comme les tables d'une BD)
- Chaque DataTable contient une propriété Columns qui contient les DataColomn (les colonnes ou champs des BD) et une propriété Rows qui contient des DataRow (Les lignes ou enregistrements des BD)
DataColumn contient des informations sur le type du champ.
DataRow permet d'accéder aux données.
Un DataSet possède aussi la propriété Constraints qui contient les Constraint (Clé primaire ou clé étrangère), et la propriété Relations qui contient les DataRelations (Relation entre les tables).
On peut créer des DataTable 'autonomes' et y mettre une table provenant d'un dataSet:
On peut créer des DataView: Vue, représentation d'une table. A partir d'une table, on peut créer plusieurs DataView avec des représentations différentes: DataView trié, DataView donc les lignes ont été filtrées (RowFilter), DataView ne comportant qu'une colonne..
Enfin une DataTable ou un DataView peut être affiché dans un contrôle (grid par exemple).
En conclusion: on connecte la base de donnée au DataSet par l'intermédiaire de Connexion et DataAdapter. Ensuite, il y a 2 manières de 'travailler':
- A - On utilise les membres du DataSet pour lire ou modifier les données.
- B - On lie un DataSet, une DataTable ou un DataView à un contrôle DataGrid ou ListBox.. c'est le Data Binding.
XVII-E-2. Utilisation du DataSet, du DataView: en pratique
Ici on utilise uniquement du code.
Soit une base de données Access nommée 'Nom.mdb', elle contient une table 'FichePatient' qui contient les champs (ou colonnes) 'Nom', 'Prenom'.
Je vais me connecter à cette base, extraire les enregistrements de la table 'FichePatient' et les mettre dans un DataSet. Chaque ligne du DataSet contient un patient. Je travaillerais sur ces lignes.
En tête du module, il faut importer l'espace de nom permettant d'utiliser les DataSet et OleDB.
Imports System. Data
Imports System. Data . OleDb
|
Dans la zone Général, Déclarations du module, il faut déclarer les objets Ado:
Private ObjetConnection As OleDbConnection
Private ObjetCommand As OleDbCommand
Private ObjetDataAdapter As OleDbDataAdapter
Private ObjetDataSet As New DataSet ()
Private strSql As String
Private ObjetDataTable As DataTable
Private ObjetDataRow As DataRow
Private RowNumber As Integer
Private strConn As String
Private ObjetCommandBuilder As OleDbCommandBuilder
|
'Ouverture
strConn = " Provider=Microsoft.Jet.OLEDB.4.0; " _
" Data Source= c:\nom.mdb; "
strSql = " SELECT FICHEPATIENT.* FROM FICHEPATIENT "
ObjetConnection = New OleDbConnection ()
ObjetConnection. ConnectionString = strConn
ObjetConnection. Open ()
ObjetCommand = New OleDbCommand (strSql)
ObjetDataAdapter = New OleDbDataAdapter (ObjetCommand)
ObjetCommand. Connection () = ObjetConnection
ObjetDataAdapter. Fill (ObjetDataSet, " FICHEPATIENT " )
ObjetDataTable = ObjetDataSet. Tables (" FICHEPATIENT " )
|
Ici le code est simplifié, mais dans la réalité, il est indispensable d'user de Try Catch pour capter les exceptions surtout pour ObjetConnection.Open() et pour l'update.
Les extraits (snippets) de VB 2005, donne un exemple de code plus condensé pour ouvrir un DataSet:
Dim conn As String = " Provider=Microsoft.Jet.OLEDB.4.0; _
Data Source= AccessFile. mdb ;Persist Security Info= False "
Dim cmd As String = " Select * from Topics "
Dim adapter As New OleDbDataAdapter (cmd, conn)
Dim topics As New Data. DataSet
adapter. Fill (topics)
|
Voir un enregistrement:
Routine affichant un enregistrement:
Une TextBox nommée 'Nom' et une TextBox 'Prenom' afficheront les noms et prénom des patients.
On rappelle que RowNumber est une variable contenant le numéro de la ligne en cours ( allant de 0 à Rows.Count-1)
If RowNumber < 0 Then Exit Sub
If RowNumber > ObjetDataTable. Rows . Count - 1 Then Exit Sub
Me. Nom . Text = ObjetDataTable. Rows (RowNumber). Item (" Nom " ). ToString
Me. Prenom . Text = ObjetDataTable. Rows (RowNumber). Item (" Prenom " ). ToString
|
Pour se déplacer:
Voir la ligne suivante par exemple:
RowNumber + = 1 incrémente le numéro de la ligne en cours puis on affiche par:
Me. Nom . Text = ObjetDataTable. Rows (RowNumber). Item (" Nom " ). ToString
Me. Prenom . Text = ObjetDataTable. Rows (RowNumber). Item (" Prenom " ). ToString
RowNumber - = 1 pour la précédente.
RowNumber = 0 pour la première.
RowNumber = ObjetDataTable. Rows . Count - 1 pour la dernière.
|
On remarque qu' il n'y a pas d'enregistrement courant, pas de pointeur sur un enregistrement, c'est vous même qui gérez 'RowNumber' une simple variable qui contient le numéro de l'enregistrement (l'index du DataRow) sur lequel vous travaillez.
Modifier un enregistrement:
ObjetDataRow = ObjetDataSet. Tables (" FICHEPATIENT " ). Rows (RowNumber)
ObjetDataRow (" Nom " ) = Me. Nom . Text
ObjetDataRow (" Prenom " ) = Me. Prenom . Text
ObjetCommandBuilder = New OleDbCommandBuilder (ObjetDataAdapter)
ObjetDataAdapter. Update (ObjetDataSet, " FICHEPATIENT " )
ObjetDataSet. Clear ()
ObjetDataAdapter. Fill (ObjetDataSet, " FICHEPATIENT " )
ObjetDataTable = ObjetDataSet. Tables (" FICHEPATIENT " )
|
Attention: quand la commande Update est effectuée, si l'enregistrement ne répond pas au spécification de la base ( doublon alors que c'est interdit, pas de valeur pour une clé primaire, Champ ayant la valeur Null alors que c'est interdit..), une exception est levée; si vous ne l'avez pas prévue cela plante!!
Il faut donc mettre la ligne contenant l'Update dans un Try Catch.
Ajouter un enregistrement:
ObjetDataRow = ObjetDataSet. Tables (" FICHEPATIENT " ). NewRow ()
ObjetDataRow (" Nom " ) = Me. Nom . Text
ObjetDataRow (" Prenom " ) = Me. Prenom . Text
ObjetDataSet. Tables (" FICHEPATIENT " ). Rows . Add (ObjetDataRow)
ObjetCommandBuilder = New OleDbCommandBuilder (ObjetDataAdapter)
ObjetDataAdapter. Update (ObjetDataSet, " FICHEPATIENT " )
ObjetDataSet. Clear ()
ObjetDataAdapter. Fill (ObjetDataSet, " FICHEPATIENT " )
ObjetDataTable = ObjetDataSet. Tables (" FICHEPATIENT " )
|
il peut y avoir génération d'une exception au niveau de la ligne Update si l'Objet Datarow présente un 'défaut', par exemple si un champ de l'ObjetDatarow a une valeur null (il n'a pas été renseigné) alors qu'il sert l'index.
Effacer l'enregistrement en cours:
ObjetDataSet. Tables (" FICHEPATIENT " ). Rows (RowNumber). Delete ()
ObjetCommandBuilder = New OleDbCommandBuilder (objetDataAdapter)
ObjetDataAdapter. Update (objetDataSet, " FICHEPATIENT " )
|
Fermer
ObjetConnection = Nothing
ObjetCommand = Nothing
ObjetDataAdapter = Nothing
ObjetDataSet = Nothing
ObjetDataTable = Nothing
ObjetDataRow = Nothing
|
Trier,Filtrer, rechercher.
Il existe une méthode Select pour les DataTable mais qui retourne des DataRow.
Dim expression As String = " NOM='LASSERRE' "
Dim sortOrder As String = " Nom DESC "
Dim foundRows () As DataRow
foundRows = ObjetDataTable. Select (expression, sortOrder)
Dim objetDatat1 As New DataTable
For Each r As DataRow In foundRows
objetDatat1. ImportRow (r)
Next
Dim dv As New DataView (objetDatat1)
DataGrid1. DataSource = dv
|
Travailler sur une DataTable.
Comment ajouter une ligne (Row)
Dim LeNewRow As DataRow = ObjetDataTable. NewRow ()
LeNewRow (" NOM " ) = " Smith "
ou
LeNewRow (1 ) = " Smith "
ObjetDataTable. Rows . Add (LeNewRow)
|
Utiliser un DataView.
Mais on peut aussi passer la table dans un DataView et utiliser Find Sort RowFilter sur le DataView.
Le DataView est un objet qui ressemble à une table mais qui correspond à une représentation et permet les tris ou l'utilisation d'un filtre:
Dim dv As DataView
dv. Table = ObjetDataSet. Tables (" FICHEPATIENT " )
|
ou
Dim dv As New DataView (ObjetDataSet. Tables (" FICHEPATIENT " ))
|
ensuite on peut trier le DataView:
On peut filtrer le DataView:
dv. RowFilter = " PreNom = 'Philippe' "
|
Le DataView ne contient plus que les rows dont la col ="Philippe". On peut afficher dans une grid.
DataGrid1. DataSource = objetDataView
|
On peut rechercher dans le DataView avec Find:
Dim dv As DataView = New DataView (Mytable)
dv. Sort = " CustomerID "
Dim i As Integer = dv. Find (" DUPONT " )
Console. WriteLine (dv (i))
|
Il existe 'FindRows' qui retourne des DataRow.
Ensuite on peut lier le DataView à une Grid.
XVII-E-3. Remplir un DataGrid ou une ListBox avec un DataSet
Une fois que le dataSet existe, en UNE ligne de code, on peut l'afficher dans un DataGrid.(Grille avec des lignes et des colonnes comme un tableur)
DataGrid1.SetDataBinding(ObjetDataSet, "FICHEPATIENT") en VB2003 on associe le dataset à la grid
On peut aussi passer par l'intermédiaire d'une DataTable en VB 2003 et VB 2005:
Dim matable As New DataTable
matable = ObjetDataSet. Tables (" FICHEPATIENT " )
DataGrid1. DataSource = matable
|
Remplir une Listbox ligne par ligne:
Dim matable As New DataTable
matable = ObjetDataSet. Tables (" FICHEPATIENT " )
Dim Ligne As DataRow ()
For Each Ligne In Matable. Rows
List1. Items . Add (ligne. Item (" Nom " ))
Next
|
XVII-E-4. Étudions en détail un DataSet
Un DataSet est un cache de données en mémoire. On a vu qu'on pouvait le remplir avec une base de données mais on peut imaginer le créer de toute pièce et le remplir en créant des tables, des colonnes, des données.
Dans un DataSet on peut donc ajouter des tables, dans les tables des colonnes, des enregistrements.
L'exemple suivant crée un objet DataTable, qui sera ajouté au DataSet.
Private myDataSet As DataSet
Dim myDataTable As DataTable = new DataTable (" ParentTable " )
Dim myDataColumn As DataColumn
Dim myDataRow As DataRow
myDataColumn = New DataColumn ()
myDataColumn. DataType = System. Type . GetType (" System.Int32 " )
myDataColumn. ColumnName = " id "
myDataColumn. ReadOnly = True
myDataColumn. Unique = True
myDataTable. Columns . Add (myDataColumn)
myDataColumn = New DataColumn ()
myDataColumn. DataType = System. Type . GetType (" System.String " )
myDataColumn. ColumnName = " ParentItem "
myDataColumn. AutoIncrement = False
myDataColumn. Caption = " ParentItem "
myDataColumn. ReadOnly = False
myDataColumn. Unique = False
myDataTable. Columns . Add (myDataColumn)
Dim PrimaryKeyColumns (0 ) As DataColumn
PrimaryKeyColumns (0 )= myDataTable. Columns (" id " )
myDataTable. PrimaryKey = PrimaryKeyColumns
Dim MyDataColumn2 As DataColumn = MyDataTable. Columns . Add (" CustomerID " , typeof (Int32))
MyDataColumn2. AutoIncrement = true
MyDataColumn2. AutoIncrementSeed = 100
MyDataColumn2. AutoIncrementStep = 2
|
Il est bon de la mettre en Readonly
myDataSet = New DataSet ()
myDataSet. Tables . Add (myDataTable)
Dim i As Integer
For i = 0 to 2
myDataRow = myDataTable. NewRow ()
myDataRow (" id " ) = i
myDataRow (" ParentItem " ) = " ParentItem " + i. ToString ()
myDataTable. Rows . Add (myDataRow)
Next i
End Sub
For compteur= 0 To myDataSet. Tables (" ParentTable " ). Rows . Count - 1
Element= myDataSet. Tables (" ParentTable " ). Rows . (compteur). Item (0 )
Next compteur
|
Travailler avec la Base MySQL
Pour travailler sur une base MySQL lisez le très bon didacticiel MySQLDotNet (sur developpez.com bien sur)
XVII-F. Liaison DataGrid, ListBox et base de données: le "DataBinding"
A - Comment remplir des listBox avec des tables venant de base de données?
B - Comment remplir des DataGrid avec des tables venant de base de données?
C - Comment avec quelques click et sans une ligne de code, créer une application permettant d'afficher le contenu d'une base de données? (en VB 2005)
Cette liaison de données entre une source de données et un contrôle se nomme'DATABINDING'.
XVII-F-1. Remplir une ListBox avec une colonne d'une table d'une BD
Ici, on va tout faire avec du code.
Exemple:
Dans une base de données Accès nommée 'BaseNom', j'ai une table 'NomPatient' avec plusieurs colonnes, je veux afficher la colonne des noms dans une listBox:
On peut utiliser un 'DataReader'
Voir le chapitre sur le DataReader
C'est de la 'lecture seule' très rapide.
On peut utiliser un 'DataSet', créer un 'DataTable' et la lier au contrôle.
Le DataSet est une représentation en mémoire des données. Une fois chargé on peut travailler en mode déconnecté.
Pour le remplir il faut un DataAdapter.
Bien sur il faut importer des espaces de nom:
Imports System
Imports System. Data
Imports System. Data . OleDb
|
Dans la zone déclaration de la fenêtre:
Private ObjetConnection As OleDbConnection
Private ObjetCommand As OleDbCommand
Private ObjetDataAdapter As OleDbDataAdapter
Private ObjetDataSet As New DataSet
Private strSql As String
Private ObjetDataTable As DataTable
Private strConn As String
|
Dans une routine Button1_Click créer les divers objets et remplir la listbox.
Private Sub Button1_Click (ByVal sender As System. Object , ByVal e As System. EventArgs ) Handles Button1. Click
strConn = " Provider=Microsoft.Jet.OLEDB.4.0; " & " Data Source= c:\Basenom.mdb; "
strSql = " SELECT FICHEPATIENT.* FROM FICHEPATIENT "
ObjetConnection = New OleDbConnection
ObjetConnection. ConnectionString = strConn
ObjetConnection. Open ()
ObjetCommand = New OleDbCommand (strSql)
ObjetDataAdapter = New OleDbDataAdapter (ObjetCommand)
ObjetCommand. Connection () = ObjetConnection
ObjetDataAdapter. Fill (ObjetDataSet, " FICHEPATIENT " )
ObjetDataTable = ObjetDataSet. Tables (" FICHEPATIENT " )
ListBox1. DataSource = ObjetDataSet. Tables (" FICHEPATIENT " )
ListBox1. DisplayMember = " NOM "
End Sub
|
Voilà, cela affiche la liste des noms.
Bien respecter les minuscules et majuscules dans les noms de tables et de champs+++
Récupérer la valeur d'un autre champ.
On a vu que dans la table, chaque enregistrement avait un champ 'Nom' mais aussi un champ 'NumInt' (numéro interne).
Dans les programmes, on a souvent besoin de récupérer le numéro interne (un ID) quand l'utilisateur clique sur un des noms; le numéro interne servira a travailler sur ce patient.
Exemple: comment récupérer le numéro interne 3 quand l'utilisateur clique sur 'Thomas'?
Il faut indiquer à la ListBox que la Value de chaque ligne est 'NumInt' en utilisant la propriété ListBox1.ValueMember.
Quand l'utilisateur clique sur une ligne de la ListBox, cela déclenche l'évènement ListBox1_SelectedIndexChanged, là on récupère la valeur de NumInt; elle se trouve dans ListBox1.SelectedValue (C'est un Int32).
Attention:
Les exemples de Microsoft ne fonctionnent pas!! car, on n'explique nulle part l'importance de l'ordre des lignes remplissant la ListBox.
C'est DataSource qui semble déclencher le chargement de la ListBox avec la prise en compte de DisplayMember et ValueMember.
Si on fait comme Microsoft (renseigner ListBox1.DataSource en premier):
ListBox1. DataSource = ObjetDataSet. Tables (" FICHEPATIENT " )
ListBox1. DisplayMember = " NOM "
ListBox1. ValueMember = " NUMINT "
|
ValueMember ne fonctionne pas bien, et ListBox1.SelectedValue retourne un objet de type DataRowView impossible à utiliser.
Il faut donc renseigner le DataSource en dernier.
ListBox1. DisplayMember = " NOM "
ListBox1. ValueMember = " NUMINT "
ListBox1. DataSource = ObjetDataSet. Tables (" FICHEPATIENT " )
Private Sub ListBox1_SelectedIndexChanged (ByVal sender As Object, ByVal e As System. EventArgs )
_Handles ListBox1. SelectedIndexChanged
Dim o As New Object
If ListBox1. SelectedIndex < > - 1 Then
TextBox1. Text = CType (ListBox1. SelectedValue , String )
End If
End Sub
|
XVII-F-2. Remplir un DataGrid avec une base de données via un DataSet.
Avec mise à jour de la base de donnée, si on fait une modification dans le Datagrid. Oui ça marche (Depuis que j'ai ajouté le CommandBluider).
Ici, on va tout faire avec du code.
Il faut créer une 'Connection', un DataAdapter et un DataSet, puis en UNE ligne de code, on peut l'afficher dans un DataGrid.(Grille avec des lignes et des colonnes comme un tableur), ne pas oublier le CommandBuilder sinon Update ne marche pas.
Dans la zone de déclaration:
Private ObjetConnection As OleDbConnection
Private ObjetCommand As OleDbCommand
Private ObjetDataAdapter As OleDbDataAdapter
Private ObjetDataSet As New DataSet
Private ObjetDataTable As New DataTable
Private strSql As String
Private strConn As String
Private ObjetCB As OleDbCommandBuilder
|
Le bouton ButtonAfficheGrid remplie le DataGrid avec nom.mdb table 'FICHEPATIENT'
Private Sub ButtonAfficheGrid_Click (ByVal sender As System. Object , ByVal e As System. EventArgs )
_Handles ButtonAfficheGrid. Click
strConn = " Provider=Microsoft.Jet.OLEDB.4.0; " & " Data Source= c:\nom.mdb; "
strSql = " SELECT FICHEPATIENT.* FROM FICHEPATIENT "
ObjetConnection = New OleDbConnection
ObjetConnection. ConnectionString = strConn
ObjetConnection. Open ()
ObjetCommand = New OleDbCommand (strSql)
ObjetDataAdapter = New OleDbDataAdapter (ObjetCommand)
ObjetCommand. Connection () = ObjetConnection
ObjetCB = New OleDbCommandBuilder (ObjetDataAdapter)
ObjetDataAdapter. Fill (ObjetDataSet, " FICHEPATIENT " )
ObjetDataTable = ObjetDataSet. Tables (" FICHEPATIENT " )
DataGrid1. DataSource = ObjetDataTable
End Sub
|
Le bouton ButtonMiseA jour met à jour nom.mdb si on a fait une modification dans le DataGrid.
Private Sub ButtonMiseAJour_Click (ByVal sender As System. Object , ByVal e As System. EventArgs )
_Handles ButtonMiseAJour. Click
ObjetDataAdapter. Update (ObjetDataSet, " FICHEPATIENT " )
End Sub
|
Les lignes, colonnes, nom des champs, ascenseurs... sont crées automatiquement avec la table "FICHEPATIENT"!! Génial.
On peut cliquer dans une cellule, la modifier..rajouter ou enlever des lignes.
On peut aussi remplir le Datagrid avec:
DataGrid1. DataSource = ObjetDataSet
DataGrid1. DataMember = " FICHEPATIENT "
|
En mode Design, on peut modifier l'aspect du DataGrid dans la fenêtre de propriété ou en utilisant la mise en forme automatique (lien en bas de la fenêtre de propriétés.)en VB 2003!!
XVII-F-3. Remplir un contrôle avec une source de données avec le moins de code possible(VB 2005 2008).
Ici, on va créer une source de données (sans code, avec l'IDE).puis on fera un binding sur le contrôle d'abord avec du code puis sans code.
On a une base de données Access (Nom.MDB), on veut afficher le contenu d'une des tables (la table 'FICHEPATIENT') dans une grille.
- Il faut créer une source de données: la BD Nom.MDB.
- Il faut créer l'interface utilisateur.
- Il faut créer les liens entre cette interface et une table de la BD.
XVII-F-3-a. Création de la source de données
On veut créer sans code une source de données:
Menu 'Données'=> 'Ajouter une nouvelle source de données'
Ici la source de données est une base de données:
On clique sur 'Base de données' puis bouton 'Suivant'.
Ensuite il faut faire le choix de la connexion (Cela correspond au choix d'une base de données existante).
Cliquer sur 'Nouvelle connexion'. Une nouvelle fenêtre nommée 'Ajouter une connexion' s'ouvre:
Indiquer le type de source de données (ici Microsoft Access (OLEDB), puis le nom de la base de données; enfin cliquer sur "Ok".
On retrouve le nom de la bd dans la zone connexion, cliquer sur "Suivant".
Ensuite VB vous demande s'il faut copier la BD dans le projet: Si oui la BD sera copiée dans le répertoire de travail quand vous installerez votre application. A vous de voir.
Ensuite VB vous propose d'enregistrer les chaînes de connexion (nom de la base...) dans le fichier de configuration afin qu'elles soient stockées et lues lors de l'utilisation ultérieure. (Automatiquement bien sur) A vous de voir.
Ensuite il faut choisir dans la base les objets qui seront chargés dans le dataset.
C'est habituellement les Tables. Cocher 'Tables'.
Cliquer sur "Terminer".
Pour voir les sources de données, cliquer sur le menu 'Données' puis 'Voir les sources de données'.
On voit bien dans notre exemple 'NOMDataSet' le DataSet de la source de données qui contient FICHEPATIENT.
XVII-F-3-b. Liaison source de données-Grid avec du code.
Maintenant qu'on a la source de données, on va créer un DataAdapter et une Grid qu'on va remplir grâce à sa propriété 'DataSource'.
On utilisera la méthode Fill du TableAdapter.
Private Sub Form1_Load
Dim FPTableAdapter = New NOMDataSetTableAdapters. FICHEPATIENTTableAdapter
FPTableAdapter. Fill (NOMDataSet. FICHEPATIENT )
End Sub
|
Il faut ensuiteajouter une grid puis faire le lien DataSet-Grid.
Dans les propriétés de DataGrid il faut enseigner DataSource et DataMember.
On exécute, la grille se remplit avec les données.
Comment enregistrer les modifications de la grid effectuées par l'utilisateur dans la base de données:
Pour que les modifications de la grille soient répercutées dans le DataSet, il faut enregistrer le DataSet dans la base grâce au TableAdapter et à sa méthode Update.
Private Sub Enregistrer_Click
Dim PatTableAdapter = New NOMDataSetTableAdapters. FICHEPATIENTTableAdapter
NOMDataSetBindingSource. EndEdit ()
If NOMDataSet. HasChanges Then
PatTableAdapter. Update (NOMDataSet. FICHEPATIENT )
End If
End Sub
|
XVII-F-3-c. Génération automatique de l'interface utilisateur
Plutôt que de faire le binding 'à la main' et taper du code comme ci-dessus, on peut tout faire faire par VB.
Visual Studio dispose d'une fenêtre 'Sources de données' depuis laquelle vous pouvez faire glisser des éléments jusqu'à un formulaire pour créer automatiquement des contrôles liés aux données qui affichent des données.
Afficher les sources de données:
Menu 'Données' puis 'Afficher les sources de données'
Il apparaît à droite la fenêtre 'Sources de données'
Dérouler 'NomDataSet'(c'est le nom donné par VB à la connexion) et cliquer sur 'FICHEPATIENT' (c'est le nom d'une table de la BD).
Enfin faire un drag and drop à partir de FICHEPATIENT et déposer le sur la form de gauche (qui est vide au départ)
Miracle: il apparaît automatiquement:
- un datagrid.
- une barre de navigation (tout est généré automatiquement: les bitmap des boutons dans les ressources Setting...)
- Un DataSet, un TableAdapter
- Un composant BindingSource.(Il fait le lien entre l'interface et la source de données)
- Un composant BindingNavigator.(Il gère la barre de navigation)
On voit bien en dessous les 4 composants qui ont été ajoutés.
C'est terminé!!
Il suffit de lancer le programme, et on voit la bd dans la grille, on se ballade dedans avec le curseur ou la barre de navigation, on peut ajouter, effacer une ligne, enregistrer les modifications:
XVII-F-3-d. Binding et TextBox
Pour générer, non pas une grid mais des zones de saisie textbox pour chaque champ, avant de faire le drag and drop, dérouler la liste contre la Table dans les sources de données et cliquer sur 'Détails'.
Il y a un exemple dans la section sur les classes, Programme à 3 couches qui donne ceci:
Les sources présentés sur cette page sont libres de droits,
et vous pouvez les utiliser à votre convenance. Par contre cette page de présentation de ces sources constitue une oeuvre intellectuelle protégée par les droits d'auteurs. Copyright © .
Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu :
textes, documents, images, etc sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à 3 ans de prison et jusqu'à 300 000 E de dommages et intérêts.
Cette page est déposée à la SACD.
|