lundi 15 avril 2019

C# Windows Form - Working with DataBases let's make a CRUD

Je me retrouve à vouloir connecter mon application Windows Form avec une Base de Données pour y travailler, comment je fais ? Je sais utiliser EntityFramework puis-je faire la même chose avec Visual Studio Community ?

Voilà le contexte de mon projet, ce n'est pas si simple j'ai "perdu" ma licence Visual Studio Professionnelle, j'ai du oublier de payer ... bref, je désinstalle Visual Studio Pro et Résinstalle Visual Studio Community pour voir.

Je créé mon premier projet C# Windows Form et maintenant j'ajoute une source de données, je créé ainsi le fichier MyDB.mdf et j'obtiens la structure du projet suivant :


C# Windows Form working with DataBases
C# Windows Form working with DataBases
Ok, on va dire que je viens de créer une connexion à une base de données mais maintenant comment je travaille avec cette base de données, il me faut faire un CRUD (Create Read Update Delete).

Dans la "boite à outils" je vois le "BindingSource" :

Windows Form working with DataBase - BindingSource
On dirait d'après l'aide que c'est le bon objet à utiliser. Mais allons voir, allons chercher un peu d'aide sur Internet :

Guru99 - C# Database Connection Tutorial with Example
Ici, il ne précise pas qu'il travaille avec Windows Form mais le CRUD est complet, on utilise un SqlDataReader et on passe des SqlCommand de façon très classique.

Connect to DataBase

A l'aide de la "Connection String" on se connecte à la Base de Donnée. Lors de la création de ma base de données Visual me donne la chaine de connexion à la base :

Data Source=(LocalDB)\MSSQLLocalDB;AttachDbFilename=D:\Users\Braby\Documents\MyBD.mdf;Integrated Security=True;Connect Timeout=30

Hum hum que faire ensuite ...

Du coup sur ma "Form1" je créé un bouton "Connect" et un labelMessage :

C# Windows Form - Working with DataBases - Connect
J'ajoute un peu de code derrière mon bouton "Connect" et lors de l'exécution cela fonctionne de la façon suivante :

C# Windows Form - Working with DataBases - Connect to database
La suite de l'exemple de Guru99 utilise un SqlDataReader pour lire la base de donnée. Il utilise un SqlDataAdapter pour insérer dans la base grâce au SqlCommand pour la mise à jour et pour la suppression des données de la base également.

Les SqlCommand sont des chaines de caractères, c'est souple et c'est la base mais c'est un peu fastidieux au niveau du traitement des chaînes de caractères.

Create into DataBase

On aura besoin sans cesse de chaîne de connexion je propose donc le code suivant pour coder la chaîne de connexion utilisable partout dans l'application :

namespace WindowsFormsApp1
{
    public static class ConnectionString
    {
        public static string MyDB
        {
            get { return @"Data Source=(LocalDB)\MSSQLLocalDB;AttachDbFilename=D:\Users\Braby\Documents\MyBD.mdf;Integrated Security=True;Connect Timeout=30"; }
            set {; }
        }
    }


Gros problème avec Visual Studio Community comment créer ma data base ...


Visual Studio Community Création de la Base de Données
C'est curieux, si je ne me retenais pas, je dirais que c'est bien pourri, j'ai du passer par la création de la Table :

CREATE TABLE [dbo].[Table]
(
 [Id] INT NOT NULL PRIMARY KEY,
    [Name] NVARCHAR(50) NULL,
    [Surname] NVARCHAR(50) NULL
)


Puis impossible d'exécuter ce script, j'ai donc du faire : Générer le script ... là c'est le délire habituel de SQLServer c'est un tas de trucs vraiment inutiles dans le script ...

Un conseil gardez soigneusement les scripts ainsi générés pour les pouvoirs le rejouer. Bref ma table est crée elle s'appelle "Table" et oui j'ai pas eu le temps de changer son nom ... Grrrr !

En fait ça ne va pas fonctionner, je vous passe les détails.

Création de la Base de Données

Nouveau Table Script et la solution est dans le bouton "Mettre à jour"


Visual Studio Community - Création de la Base de Données - 1
Le bouton "Mettre à jour" génère le script :

Visual Studio Community - Création de la Base de Données - 2
Il faudrait être idiot pour renoncer si prêt du but, il n'y a plus qu'à cliquer sur "Générer le script" :

Visual Studio Community - Création de la Base de Données - 3
C'est là que je disais que le script est vraiment stupide depuis les années 2000 sql server de Microsoft est comment dire pour ne pas froisser ... POURRI ! Imbécile, idiot ... si vous avez une fois dans votre vie utilisé autre chose comme par exemple MySQL qui est si bon et si facile ... bref.

C'est lié au fait que cet idiot de SQL Server il veux toujours mettre les fichiers là où il veut et pas là ou l'utilisateur voudrait qu'ils soient. D'ailleurs si vous ne faite pas attention de là où vous créez votre base de données, je vous met au défit de la retrouver. Certain apprennent par cœur le nom du répertoire :

D:\Users\UserName\AppData\Local\Microsoft\Microsoft SQL Server Local DB\Instances\MSSQLLocalDB\master.mdf

Pour ne pas perdre leurs bases de données, je ne vous dit pas ce que cela peut entrainer d'erreurs au déploiement.

Read de la Database

Ben oui, une fois créé l'article il faudra le lire, c'est l'objectif du CRUD les JavaIste commencent donc par créer un article pour lire ensuite.

Evidemment, avec tout ça, la chaine de connexion a changée :

Data Source = (LocalDB)\MSSQLLocalDB;Initial Catalog = MyDB; Integrated Security = True; Connect Timeout = 30; Encrypt=False;TrustServerCertificate=False;ApplicationIntent=ReadWrite;MultiSubnetFailover=False

Voici le code derrière le bouton Read :

         private void buttonRead_Click(object sender, EventArgs e)
        {
            SqlDataReader dataReader;
            String sql = "Select Name, Surname, Id from TableCustomer";
            SqlCommand command = new SqlCommand(sql, Connection);


            dataReader = command.ExecuteReader();

            while (dataReader.Read())
            {
                labelRead.Text += labelRead.Text + dataReader.GetValue(0) + "-" + dataReader.GetValue(1) + Environment.NewLine;
            }
        }


Et ma table s'appelle "TableCustomer" moyennant quoi je peux passer à la création d'un Item de la table :


Visual Studio Community - Create Item
Et le code derrière bouton Create :

        private void buttonCreate_Click(object sender, EventArgs e)
        {
            SqlDataAdapter adapter = new SqlDataAdapter();
            String sql = "Insert into TableCustomer(Name, Surname) values(";
           
            // Vérifications du formulaire
            if (    textBoxName.Text != string.Empty
                 && textBoxSurname.Text != string.Empty )
            {
                sql += "'" + textBoxName.Text + "','"
                    + textBoxSurname.Text + "')";


                adapter.InsertCommand = new SqlCommand(sql, Form1.Connection);
                adapter.InsertCommand.ExecuteNonQuery();
                adapter.InsertCommand.Dispose();
            }
            else
            {
                labelMessage.Text = "Error: Name vide ou Surname vide !";
            }
        }


Update d'un article de Base

Le formulaire de mise à jour d'un article de la base est de loin de plus difficile à faire il faut aller lire permettre la mise à jour avec de faire un update avec la syntaxe SQL :

Update Table set Surname = 'aaa' where Id=2

Je vous laisse le faire ;-)

Delete en article

Delete Table where Id=3

idem ...

Utiliser les Bindings pour contrôler les data

Voilà, nous sommes au cœur du sujet, maintenant que nous savons manipuler les données nous allons les Binder directement sur une source de données pour les parcourir et les mettre à jour.

J'ai créé les trois TextBox qui vont me permettre d'afficher les données.

Je drag and drop un BindingNavigator dans ma Form3 :

Visual Studio Community - BindingNavigator
Cela doit se faire tout seul, il faut arriver à créer une source de données MyDBDataSet :
Visual Studio Community - BindingNavigator
Problème à chaque fois que j'essayais de créer ma source de données le programme me répondait "le fichier MyDB.mdf est déjà utilisé, fermé le programme qui utilise ce fichier".

nian, nian, nian ... toujours les même problèmes avec MSSqlServer ! Bref, j'ai du redémarrer ma machine certainement que pendant les tests de ce programme une connexion à la BD s'est mal terminée.

Ensuite une fois la "Sources de données" configurée, j'ai pu binder chaque TextBox de mon formulaire sur les colonnes de ma table.

Il ne me restait plus qu'à Binder mon bindingNavigator1 sur la tableCustomerBindingSource créé par le programme pour que cela fonctionne.

Winform - Binding on DataSource
Mon formulaire est binder sur ma source de données, c'est très joli mignon tout plein :
Winform Binding
Voilà, nous avons fait le tour de toutes les fonctionnalités qui permettent de manipuler des enregistrements de données à partir d'une Winform Application. C'est un peu fastidieux car il y a différentes techniques mais je montre que l'on s'en sort avec Visual Studio Community.

Have fun!