Accueil
Club Emploi Blogs   TV   Dév. Web PHP XML Python Autres 2D-3D-Jeux Sécurité Windows Linux PC Mac
Accueil Conception Java DotNET Visual Basic  C  C++ Delphi Eclipse MS-Office SQL & SGBD Oracle  4D  Business Intelligence

Cours VB.NET

Date 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:

MyConnexion.Open()
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:


'  Déclaration Objet Connexion

Private ObjetConnection As OleDbConnection

' Déclaration Objet Commande

Private ObjetCommand As OleDbCommand

'  Déclaration Objet DataAdapter

Private ObjetDataAdapter As OleDbDataAdapter

' Déclaration Objet DataSet

Private ObjetDataSet As New DataSet() 'Attention au New

'String contenant la 'Requête SQL'

Private strSql As String

' Déclaration Objet DataTable

Private ObjetDataTable As DataTable

' Déclaration Objet DataRow (ligne)

Private ObjetDataRow As DataRow

'Numéro de la ligne en cours

Private RowNumber As Integer    'Numéro de l'enregistrement courant

'Paramêtres de connexion à la DB

Private strConn As String

'Pour recompiler les données modifiées avant de les remettre dans le

'"DataAdapter"

Private ObjetCommandBuilder As OleDbCommandBuilder
'Ouverture


'Initialisation de la chaîne de paramètres pour la connexion

strConn = "Provider=Microsoft.Jet.OLEDB.4.0;"  _

"Data Source= c:\nom.mdb;"

'Initialisation de la chaîne contenant l'instruction SQL

strSql = "SELECT FICHEPATIENT.* FROM FICHEPATIENT"

'Instanciation d'un Objet Connexion

ObjetConnection = New OleDbConnection()

'Donner à la propriété ConnectionString les paramètres de connexion

ObjetConnection.ConnectionString = strConn

'Ouvrir la connexion

ObjetConnection.Open()

'Instancier un objet Commande

ObjetCommand = New OleDbCommand(strSql)

'Instancier un objet Adapter

ObjetDataAdapter = New OleDbDataAdapter(ObjetCommand)

'initialiser l'objet Command

ObjetCommand.Connection() = ObjetConnection

'Avec l'aide de la propriété Fill du DataAdapter charger le DataSet

ObjetDataAdapter.Fill(ObjetDataSet, "FICHEPATIENT")

'Mettre dans un Objet DataTable une table du DataSet

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

'Lors de l'ouverture de la BD, s'il n'y a aucun enregistrement

If RowNumber > ObjetDataTable.Rows.Count - 1 Then Exit Sub

'ObjetTable.Rows(Numéro de lignes).Item( Nom de colonne) donne le contenu 
'd'un champ dans une ligne donnée

Me.Nom.Text = ObjetDataTable.Rows(RowNumber).Item("Nom").ToString

Me.Prenom.Text = ObjetDataTable.Rows(RowNumber).Item("Prenom").ToString

'Item peut avoir en paramètre le nom de la colonne ou sont index
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:


' Extraire l'enregistrement courant

ObjetDataRow = ObjetDataSet.Tables("FICHEPATIENT").Rows(RowNumber)

 

'Modifier les valeurs des champs en  récupérant le contenu des TextBox

ObjetDataRow("Nom") = Me.Nom.Text

ObjetDataRow("Prenom") = Me.Prenom.Text

 

'Pour modifier les valeurs changées dans le DataAdapter

ObjetCommandBuilder = New OleDbCommandBuilder(ObjetDataAdapter)

 

'Mise à jour

ObjetDataAdapter.Update(ObjetDataSet, "FICHEPATIENT")

 

'On vide le DataSet et on le 'recharge' de nouveau.

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)

'Pour modifier les valeurs changées dans le DataAdapter

ObjetCommandBuilder = New OleDbCommandBuilder(ObjetDataAdapter)

'Mise à jour

ObjetDataAdapter.Update(ObjetDataSet, "FICHEPATIENT")

'On vide le DataSet et on le 'recharge' de nouveau.

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

'Objet connectée

ObjetConnection = Nothing

ObjetCommand = Nothing

ObjetDataAdapter = Nothing

'Objet déconnectée

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'"   'expression à rechercher

Dim sortOrder As String = "Nom DESC"

Dim foundRows() As DataRow     'résultat dans des DataRow

foundRows = ObjetDataTable.Select(expression, sortOrder)

Dim objetDatat1 As New DataTable

For Each r As DataRow In foundRows

objetDatat1.ImportRow(r)

Next

'MsgBox(objetDatat1.Rows.Count)

Dim dv As New DataView(objetDatat1)

DataGrid1.DataSource = dv
Travailler sur une DataTable.

Comment ajouter une ligne (Row)


Dim LeNewRow As DataRow = ObjetDataTable.NewRow()  'On crée un DataRow

LeNewRow("NOM") = "Smith"  'On remplit la première cellule

ou
LeNewRow(1) = "Smith"

ObjetDataTable.Rows.Add(LeNewRow) 'On ajoute la Row au DataTable
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:

'On crée un DataView, on y met une table.

Dim dv As DataView

dv.Table =  ObjetDataSet.Tables("FICHEPATIENT")
ou

Dim dv As New DataView(ObjetDataSet.Tables("FICHEPATIENT")) 'on met une table dans le dataview
ensuite on peut trier le DataView:

dv.Sort = "Nom DESC"  'on trie  sur le champ Nom en ordre décroissant (ASC pour un tri croissant).
On peut filtrer le DataView:

dv.RowFilter = " PreNom = 'Philippe'"  'bien respecter les  '. et les majuscules/minuscules.
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"

    ' Cherche le customer named "DUPONT" dans la première colonne
    Dim i As Integer = dv.Find("DUPONT")
    Console.WriteLine(dv(i))'Affiche sur la console
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


' Créer une nouvelle DataTable.
Dim myDataTable As DataTable = new DataTable("ParentTable")
' Declaration de variables DataColumn et DataRow objects.
Dim myDataColumn As DataColumn
Dim myDataRow As DataRow

' Créer un nouveau DataColumn, lui donner un DataType, un nom, divers valeurs pour ses propriétés  
'et l'ajouter à la DataTable.
myDataColumn = New DataColumn()
myDataColumn.DataType = System.Type.GetType("System.Int32")    'Type de la colonne
myDataColumn.ColumnName = "id"                                 'Nom de la colonne
myDataColumn.ReadOnly = True                                   'Colonne ReadOnly
myDataColumn.Unique = True                                     'Evite les doublons 
myDataTable.Columns.Add(myDataColumn)

' Créer une seconde column.
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)

'La colonne id doit être une clé primaire.
Dim PrimaryKeyColumns(0) As DataColumn
PrimaryKeyColumns(0)= myDataTable.Columns("id")
myDataTable.PrimaryKey = PrimaryKeyColumns
 

'la colonne peut être une colonne auto incrémentée: (la valeur du champ "CustomerID" démarre à 100 , 
's'incrémente de 2 automatiquement à chaque création de DataRow.

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


' Créer un objet DataSet
myDataSet = New DataSet()
' Ajouter la Table au DataSet.
myDataSet.Tables.Add(myDataTable)

' Créer 3 DataRow objects (3 lignes)  et les ajouter à la DatTable
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

 

'parcourir dans la table 'ParentTable' toutes les lignes et lire le premier élément (1ère colonne)


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:

'Déclarer la connexion

Private ObjetConnection As OleDbConnection

' Déclaration l'Objet Commande

Private ObjetCommand As OleDbCommand

' Déclaration Objet DataAdapter

Private ObjetDataAdapter As OleDbDataAdapter

' Déclaration Objet DataSet

Private ObjetDataSet As New DataSet

'String contenant la 'Requête SQL'

Private strSql As String

' Déclaration Objet DataTable

Private ObjetDataTable As DataTable

'Paramêtres de connexion à la DB

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

'Initialisation de la chaîne de paramètres pour la connexion

strConn = "Provider=Microsoft.Jet.OLEDB.4.0;" & "Data Source= c:\Basenom.mdb;"

'Initialisation de la chaîne contenant l'instruction SQL

strSql = "SELECT FICHEPATIENT.* FROM FICHEPATIENT"

'Instanciation d'un Objet Connexion

ObjetConnection = New OleDbConnection

'Donner à la propriété ConnectionString les paramètres de connexion

ObjetConnection.ConnectionString = strConn

'Ouvrir la connexion

ObjetConnection.Open()

'Instancier un objet Commande

ObjetCommand = New OleDbCommand(strSql)

'Instancier un objet Adapter

ObjetDataAdapter = New OleDbDataAdapter(ObjetCommand)

'initialiser l'objet Command

ObjetCommand.Connection() = ObjetConnection

'Avec l'aide de la propriété Fill du DataAdapter charger le DataSet

ObjetDataAdapter.Fill(ObjetDataSet, "FICHEPATIENT")

'Mettre dans un Objet DataTable une table du DataSet

ObjetDataTable = ObjetDataSet.Tables("FICHEPATIENT")

 

'Indiquer au ListBox d'afficher la table "fichepatient" (indiquer la source)

ListBox1.DataSource = ObjetDataSet.Tables("FICHEPATIENT")

'Indiquer quelle colonne afficher

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")

'Dans ce cas ListBox1.SelectedValue contient bien un Int32 correspondant au 'NutInt' selectionné.

'Ensuite on peut récupérer sans problème NumInt (et l'afficher par exemple dans une TextBox)

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:

' Déclaration Objet Connection

Private ObjetConnection As OleDbConnection

' Déclaration Objet Commande

Private ObjetCommand As OleDbCommand

' Déclaration Objet DataAdapter

Private ObjetDataAdapter As OleDbDataAdapter

' Déclaration Objet DataSet

Private ObjetDataSet As New DataSet

' Déclaration Objet DataTable

Private ObjetDataTable As New DataTable

'String contenant la 'Requête SQL'

Private strSql As String

'Paramêtres de connexion à la DB

Private strConn As String

' Déclaration d'un  OleDbCommandBuilder

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

'Initialisation de la chaîne de paramètres pour la connexion

strConn = "Provider=Microsoft.Jet.OLEDB.4.0;" & "Data Source= c:\nom.mdb;"

'Initialisation de la chaîne contenant l'instruction SQL

strSql = "SELECT FICHEPATIENT.* FROM FICHEPATIENT"

'Instanciation d'un Objet Connexion

ObjetConnection = New OleDbConnection

'Donner à la propriété ConnectionString les paramètres de connexion

ObjetConnection.ConnectionString = strConn

'Ouvrir la connexion

ObjetConnection.Open()

'Instancier un objet Commande

ObjetCommand = New OleDbCommand(strSql)

'Instancier un objet Adapter

ObjetDataAdapter = New OleDbDataAdapter(ObjetCommand)

'initialiser l'objet Command

ObjetCommand.Connection() = ObjetConnection

'initialiser l'objet OleCBComandBuilder (sinon pas d'update)

ObjetCB = New OleDbCommandBuilder(ObjetDataAdapter)

'Avec l'aide de la propriété Fill du DataAdapter charger le DataSet

ObjetDataAdapter.Fill(ObjetDataSet, "FICHEPATIENT")

'Créer une datatable à partir du dataset

ObjetDataTable = ObjetDataSet.Tables("FICHEPATIENT")

'Mettre dans le DataGrid une table  DataTable

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

    'Mettre à jour

    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

'Création d'un TableAdapter

Dim FPTableAdapter = New NOMDataSetTableAdapters.FICHEPATIENTTableAdapter

'Extraction des données et chargement du DataSet

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()

'Vérifiez que des modifications ont eu lieu

If NOMDataSet.HasChanges Then

    'Appliquer les changements dans la base de données

    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.

Vos questions techniques : forum d'entraide Accueil - Publiez vos articles, tutoriels, cours et rejoignez-nous dans l'équipe de rédaction du club d'entraide des développeurs francophones. Nous contacter - Copyright 2000..2005 www.developpez.com