Développer avec une architecture en Csharp

Apprenez à développer avec une architecture en C#

Une architecture est un ensemble de règles établies permettant à un développeur de concevoir des applications selon une organisation particulière.

16 commentaires Donner une note à l'article (4)

Article lu   fois.

L'auteur

Profil ProSite personnel

Liens sociaux

Viadeo Twitter Facebook Share on Google+   

I. Introduction

Comme énoncé plus haut, le but de ce tutoriel est de nous permettre de faire une application basée sur une architecture. Je tenais à préciser que ce tutoriel n'est pas le premier du genre pour la simple et bonne raison qu'un auteur a déjà publié trois articles Partie 1, Partie 2 et Partie 3. Au moment de la rédaction, je n'ai nullement l'intention de critiquer ou déprécier son article, seulement le présent tutoriel aborde le même principe de développement, mais d'une autre manière.

II. Préambule

Ce qu'il faut retenir, c'est qu'une architecture est élaborée selon les besoins et aspirations de celui qui l'a écrite, j'ai eu à bosser avec un ami sur une architecture compliquée. Pourquoi ? Simplement parce qu'elle répondait à ses exigences. Dans les parties suivantes, nous expliquerons les principes de base d'une architecture, cependant vous devriez obligatoirement vous familiariser à certains mots et concepts tels que la Programmation Orientée, couche métier, couche physique, couche d'accès aux données et bien d'autres. Avant de vous lancer je vous conseille de faire un tour sur ces articles Programmation orientée objet, TSQL. Vous serez ensuite prêt pour vous lancer dans ce tutoriel.

III. Présentation d'un modèle d'architecture

La présentation consistera en l'énumération des grandes parties de notre architecture et comment elle fonctionne. Voici donc un schéma qui retrace son fonctionnement.

Image non disponible

IV. Explication

Selon l'image ci-dessus, nous prenons connaissance de la couche métier, couche d'accès aux données, couche physique et la couche interface.

IV-A. La couche interface

Cette couche se matérialise par les interfaces utilisateur (les fenêtres, boutons, les zones de texte). Dans la couche interface, nous ne ferons qu'instancier les méthodes des objets de la couche métier.

IV-B. La couche métier

La couche métier contient des méthodes qui seront utilisées par les utilisateurs. Lorsqu'un utilisateur procède par exemple à une insertion ou une modification, ce sont ces méthodes créées dans la couche métier qui seront appelées. Elle permet de définir aussi les règles de validation de formulaire.

IV-C. La couche d'accès aux données

Cette couche se scinde en deux parties. Une première qui permet de décrire les entités de notre base de données (comme entité nous pourrons avoir des classes, des structs dont les propriétés devront être identiques à celles de vos tables au niveau de votre base de données) et une deuxième dans laquelle nous écrirons des méthodes qui sont relatives aux bases de données. Dans cette seconde couche, nous écrirons des fonctions qui porteront sur des opérations de base telles que l'insertion, la modification, la sélection et la suppression. L'écriture de ces méthodes dépendra du Système de Gestion de Base de Données. Étant donné que nous utiliserons le langage Csharp et une base de données SQL Server Express, nous utiliserons également des espaces de noms qui sont spécifiques à notre base de données. Pour une base de données SQL Server nous aurons System.Data, System.Data.SqlClient et MySql.Data, MySql.Data.MySqlClient pour une base de données MySQL et vice versa. Vos méthodes dépendront du SGBD que vous utiliserez. Cependant, sachez que les méthodes de la couche d'accès aux données sont créées en fonction des scripts que nous aurons écrits au niveau de notre base de données, la couche physique.

IV-D. La couche physique

Elle contient les scripts de création de notre base de données et les opérations du CRUD (Create Read Update and Delete) et d'autres requêtes selon les fonctionnalités de l'application ou les besoins des utilisateurs. De façon plus simple, la couche physique c'est notre Système de Gestion de Base de Données (SGBD).

V. Miniprojet par la pratique

Pour mieux appréhender le développement avec une architecture, je vous propose de concevoir une petite application qui nous permettra d'enregistrer des clients avec leurs contacts. La table client possédera les propriétés nom, prénom, téléphone et adresse.

À partir de ce modèle, nous créerons notre base de données sous SQL Server Express avec les scripts suivants :

  • Insertion ;
  • Modification ;
  • Sélection ;
  • Suppression ;
  • Vérification avant insertion (cette procédure stockée permettra de vérifier les numéros des clients avant leur insertion).

VI. Base de données

Ouvrez Microsoft SQL Server et créez la base de données. Faites un clic droit sur Databases et cliquez sur New Database et nommez la base de données architecture.

VI-A. Le script de création de la table

Script de création de la table
CacherSélectionnez
CREATE TABLE client(
    id int primary key identity(1,1),--La colonne étant auto-incrémentée
    nom varchar(20),
    prenom varchar(30),
    tel varchar(15),
    adresse varchar(50)
);

VI-B. Le script de création des procédures stockées

Nous allons donc créer nos procédures stockées, elles sont faites au niveau de notre SGBD, pour notre tutoriel, il s'agit de SQL Server Express.

VI-B-I. L'insertion

Insertclient
CacherSélectionnez
CREATE PROCEDURE InsertClient
(
/*Définition des paramètres 
en Transact-SQL les variables doivent être précédées du caractère @
*/
    @nom varchar(20),
    @prenom varchar(30),
    @tel varchar(15),
    @adresse varchar(50)
)
AS
INSERT INTO client(nom,prenom,tel,adresse) VALUES (@nom,@prenom,@tel,@adresse)

VI-B-II. La modification

Procédure UPDATE
Sélectionnez
CREATE PROCEDURE UpdateClient(
--Définition des paramètres de notre procédure
    @id int,
    @nom varchar(20),
    @prenom varchar(30),
    @tel varchar(15),
    @adresse varchar(50)
)
AS
UPDATE Client 
SET 
    nom=@nom,
    prenom=@prenom,
    tel=@tel,
    adresse=@adresse
WHERE(client.id=@id)

VI-B-III. La sélection

Procédure Select
Sélectionnez
CREATE PROCEDURE SelectClient
AS
SELECT id,nom,prenom,tel,adresse from client;

VI-B-IV. La suppression

Procédure Delete
CacherSélectionnez
CREATE PROCEDURE DeleteClient
(
    @Id int
)
AS
DELETE FROM client
WHERE(client.id=@Id);

VI-B-V. La vérification

Procédure de vérification
CacherSélectionnez
CREATE PROCEDURE VerifNumeroBeforeInsert
(
    @Numero varchar(15)
)
AS
SELECT COUNT(*) as 'Nombre' FROM client
WHERE(client.tel=@Numero);

VII. Projet en Csharp

Après création des méthodes, nous aborderons la partie code de notre tutoriel. Pour cela, nous allons créer notre solution sous Visual Studio, nommez-la architecture et ensuite vous y ajouterez trois projets de classe nommés respectivement client_metier, client_data, client_structure. À la fin vous devriez avoir une structure comme celle ci-dessous.

Image non disponible

VIII. Code

Maintenant que notre solution est créée, nous procéderons à l'écriture de nos couches. Pour ce faire, nous commencerons par la couche d'accès aux données. Cette couche se subdivise en deux parties. Une partie qui permettra de décrire les objets (classes ou structures de données) et une deuxième dans laquelle nous définirons les méthodes qui implémenteront les scripts que nous avons précédemment créés au niveau de la base de données.

VIII-A. La description (couche d'accès aux données)

Voici un exemple de la structure. Cette partie nous permettra de définir les objets que nous utiliserons dans notre application. Notez que ces objets sont créés en tenant compte des structures des tables de notre base de données. Pour notre minitutoriel, nous utiliserons des struct plutôt que des classes (Classes et structures).

Image non disponible

Nous avons commencé par cette partie, car l'écriture des couches métier, les méthodes d'accès aux données en dépend.

VIII-B. Les méthodes d'accès aux données

Pour notre exemple, nous n'avons que cinq méthodes, mais elles peuvent varier selon le projet sur lequel vous travaillerez. Nous allons donc créer nos méthodes, lesquelles serviront d'intermédiaire entre notre application et notre moteur de base de données. Ouvrez votre éditeur, ajoutez une classe au projet client_data que vous nommerez clientdata et nous ajouterons nos codes.

  • L'insertion
insertclient
CacherSélectionnez
public int insertclient(client notreclient)
        {
            SqlConnection cnx = new SqlConnection(connexion);
            cnx.Open();
            SqlCommand cmd = new SqlCommand("insertclient",cnx);
            cmd.CommandType = CommandType.StoredProcedure;
            SqlParameter prmnom = new SqlParameter("nom",SqlDbType.VarChar,20);
            prmnom.Value = notreclient.nom;
            cmd.Parameters.Add(prmnom);
            SqlParameter prmprenom = new SqlParameter("prenom", SqlDbType.VarChar, 20);
            prmprenom.Value = notreclient.prenom;
            cmd.Parameters.Add(prmprenom);
            SqlParameter prmtel = new SqlParameter("tel", SqlDbType.VarChar, 20);
            prmtel.Value = notreclient.tel;
            cmd.Parameters.Add(prmtel);
            SqlParameter prmadresse = new SqlParameter("adresse", SqlDbType.VarChar, 20);
            prmadresse.Value = notreclient.adresse;
            cmd.Parameters.Add(prmadresse);
            int resultat = Convert.ToInt32(cmd.ExecuteNonQuery());
            return resultat;
        }
  • La mise à jour

    updateclient
    Sélectionnez
    public int updateclient(client notreclient)
            {
                SqlConnection cnx = new SqlConnection(connexion);
                cnx.Open();
                SqlCommand cmd = new SqlCommand("updateclient", cnx);
                cmd.CommandType = CommandType.StoredProcedure;
                SqlParameter prmid = new SqlParameter("id", SqlDbType.Int, 20);
                prmid.Value = notreclient.nom;
                cmd.Parameters.Add(prmid);
                SqlParameter prmnom = new SqlParameter("nom", SqlDbType.VarChar, 20);
                prmnom.Value = notreclient.nom;
                cmd.Parameters.Add(prmnom);
                SqlParameter prmprenom = new SqlParameter("prenom", SqlDbType.VarChar, 20);
                prmprenom.Value = notreclient.prenom;
                cmd.Parameters.Add(prmprenom);
                SqlParameter prmtel = new SqlParameter("tel", SqlDbType.VarChar, 20);
                prmtel.Value = notreclient.tel;
                cmd.Parameters.Add(prmtel);
    
                SqlParameter prmadresse = new SqlParameter("adresse", SqlDbType.VarChar, 20);
                prmadresse.Value = notreclient.adresse;
                cmd.Parameters.Add(prmadresse);
                int resultat = Convert.ToInt32(cmd.ExecuteNonQuery());
                return resultat;
            }
  • La suppression

    deleteclient
    Sélectionnez
     public void deleteclient(int notreclient)
    //On passe l'identifiant du client en paramètre
            {
                SqlConnection cnx = new SqlConnection(connexion);
                cnx.Open();
                SqlCommand cmd = new SqlCommand("deleteclient", cnx);
                cmd.CommandType = CommandType.StoredProcedure;
    
                //Ajout des paramètres
                SqlParameter prmid = new SqlParameter("id", SqlDbType.Int, 0);
                prmid.Value = notreclient;
                cmd.Parameters.Add(prmid);
    
                //Exécution
                cmd.ExecuteNonQuery();
            }
  • La sélection

    selectclient
    Sélectionnez
     public DataTable selectclient()
            {
                SqlConnection cnx = new SqlConnection(connexion); //Notre connexion à la base de données
                cnx.Open(); //Ouverture de la connexion
                SqlCommand cmd = new SqlCommand("selectclient", cnx); //Initialisation de la commande 
                cmd.CommandType = CommandType.StoredProcedure; //Ici nous précisons le type de notre commande qui est en fait une procédure stockée
    
                DataTable dt = new DataTable(); //Une table de données en mémoire
                SqlDataAdapter adaptater = new SqlDataAdapter(cmd); 
                adaptater.Fill(dt);
                return dt;
            }
  • La vérification
vérification
Sélectionnez
/*Cette méthode permettra de vérifier l'existence d'un numéro
          C'est-à-dire que lorsque nous ajouterons un nouveau client, nous allons 
         nous assurer que ce numéro n'est pas déjà utilisé par quelqu'un d'autre*/
        public DataTable verifclientbeforeinsert(string paramNumero)
{
            SqlConnection cnx = new SqlConnection(connexion); //Notre connexion à la base de données
            cnx.Open(); //Ouverture de la connexion
            SqlCommand cmd = new SqlCommand("VerifNumeroBeforeInsert", cnx); //Initialisation de la commande 
            cmd.CommandType = CommandType.StoredProcedure; //Ici nous précisons le type de notre commande qui est en fait une procédure stockée
            DataTable dt = new DataTable(); //Une table de données en mémoire
            SqlDataAdapter adaptater = new SqlDataAdapter(cmd);
            adaptater.Fill(dt);
            return dt;
        }

IX. Couche métier

Pour notre couche métier, nous allons donc décrire nos objets. Cela doit être fait selon les tables de notre base de données. Voici un exemple de notre couche métier.

Couche métier
Sélectionnez
using System;
using System.Collections.Generic;
using System.Linq;
using client_structure; //Notre couche de destruction
using client_data; //On inclue notre couche d'accès aux données
using System.Text;

namespace client_metier
{
   public class clientmetier
   {
       #region Propriétés publiques

       public int id
       {
           get { return _id; }
           set { _id = value; }
       }

        public string nom
       {
           get { return _nom; }
           set { _nom= value; }
       }

        public string prenom
        {
            get { return _prenom; }
            set { _prenom = value; }
        }

        public string tel
        {
            get { return _tel; }
            set { _tel = value; }
        }

        public string adresse
        {
            get { return _adresse; }
            set { _adresse = value; }
        }
       #endregion
       #region Propriétés privées
        int _id;
        string _nom;
        string _prenom;
        string _tel;
        string _adresse;
       #endregion
   }
}

Comme vous le voyez, nous avons deux sortes de déclarations. Celles commençant par le mot-clé public(qui seront accessibles partout) et celles avec le mot private(qui ne seront accessibles que par les objets de la classe). En plus de la description, nous allons également utiliser un objet dans cette couche qui permettra de faire le mapping entre la couche métier et la couche interface. C'est-à-dire que cet objet servira d'intermédiaire en quelque sorte. Dans l'exemple ci-dessous, vous avez la déclaration de notre objet.

Couche métier
Sélectionnez
#region Objet de mapping
        client NotreClient
        { 
            //On déclare donc ces propriétés uniquement en lecture
            get 
            {
                client LeClient;
                LeClient.id = this._id;
                LeClient.nom = this._nom;
                LeClient.prenom=this._prenom;
                LeClient.adresse = this.adresse;
                LeClient.tel = this._tel;
                return LeClient;
            }
        }
        #endregion

Après avoir défini notre objet, nous allons donc écrire les méthodes de notre traditionnel CRUD (entendez par là l'insertion, la lecture, la modification et la suppression).

Méthodes du CRUD
Sélectionnez
#region Les méthodes de notre CRUD

       //Méthode d'insertion
        public int Insertclient()
        {
            unclientdata = new clientdata();
            return unclientdata.insertclient(NotreClient); //La méthode d'insertion retourne un entier
        }

       //Méthode de modification
        public int Updateclient()
        {
            unclientdata = new clientdata();
            return unclientdata.updateclient(NotreClient);
        }

       //Méthode de suppression
        public void Deleteclient(int idclient)
        {
            unclientdata = new clientdata();
            unclientdata.deleteclient(idclient);
        }

        public DataTable Selectclient()
        {
            unclientdata = new clientdata();
            return unclientdata.selectclient();
        }

        public int VerifNumero(string Numero)
        {
            unclientdata = new clientdata();
            return unclientdata.verifclientbeforeinsert(Numero);
        }

        #endregion

X. Couche interface

Ajoutez un projet de type WindowsFormsApplication à votre projet et faites en sorte que votre formulaire ressemble à quelque chose comme l'image ci-dessous.

Image non disponible

Nous allons donc procéder aux différentes opérations sur notre base de données.

Pour cela, nous devrons impérativement instancier un objet de la classe métier. Voici donc un extrait du code de notre bouton, mais avant n'oubliez pas d'importer les espaces de noms requis et d'ajouter une référence à notre couche métier (clic droit sur le projet et sélectionner « Ajouter référence » et sélectionner la couche métier) ensuite vous devrez l'inclure comme l'exemple ci-dessous.

Inclusion de notre couche métier
Sélectionnez
using client_metier;//Référence à la couche métier
Instanciation d'un objet métier
Sélectionnez
        #region Propriétés privées
        clientmetier unclient = null;
        #endregion

X-A. L'insertion et la vérification

En ce qui concerne l'insertion, nous devons nous assurer que le numéro entré n'est utilisé par aucun client. Avec le code l'explication sera beaucoup plus facile.

Méthode d'insertion
Sélectionnez
public void insertclient(string numero, string nom, string prenom, string adresse)
        {
            unclient = new clientmetier();
            int verif = unclient.VerifNumero(numero); //Méthode vérification des numéros avant insertion que nous avons écrite dans la couche métier
            if (verif == 0) //Si vrai alors le numéro n'existe pas
            {
                //Assignation
                unclient.nom = nom;
                unclient.prenom = prenom;
                unclient.tel = numero;
                unclient.adresse = adresse;

                //Insertion
                unclient.Insertclient(); //Méthode d'insertion 
                cleanfields(); //Cette méthode vide le contenu des champs
            }
            else
            {
                //Sinon on affiche un message d'erreur à l'utilisateur
                MessageBox.Show("Ce numéro existe déjà", "Erreur", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

Et pour finir, la méthode d'insertion est appelée derrière le bouton comme suit

Bouton Insert
Sélectionnez
 private void button1_Click(object sender, EventArgs e)
        {
            insertclient(txttel.Text,txtnom.Text,txtprenom.Text,txtadresse.Text);
            cleanfields();
            loaddata(); //Méthode d'affichage des données.
        }

X-B. La sélection

Pour effectuer une sélection, cela est possible grâce à un espace de noms qui est le system.Data. C'est pourquoi nous avons cette ligne.

system,Data
Sélectionnez
using System.Data;

Voici la méthode sélection

Sélection
Sélectionnez
 public void loaddata()
        {
            AllClient = new System.Data.DataTable(); 
            unclient = new clientmetier();
            AllClient = unclient.Selectclient();//Notre méthode écrite dans la couche d'accès aux données retourne un DataTable
            listView1.Items.Clear(); //Suppression de la liste avant d'y afficher les données
            foreach (DataRow dtr in AllClient.Rows)
            {
                //Le DataRow nous permet de parcourir chaque ligne du DataTable(qui est une table de données en mémoire)
                int id =0;
                string nom = null;
                string prenom = null;
                string tel = null;
                string adresse = null;
                //Nous recueillons les valeurs en fonction du nom des colonnes et nous procédons à l'assignation
                id = (int)dtr["id"];
                nom = (string)dtr["nom"].ToString();
                prenom = (string)dtr["prenom"].ToString();
                adresse = (string)dtr["adresse"].ToString();
                tel = (string)dtr["tel"].ToString();
                //Fin assignation
                ListViewItem itm = listView1.Items.Add(nom);
                itm.SubItems.Add(prenom);
                itm.SubItems.Add(tel);
                itm.SubItems.Add(adresse);
                itm.Tag = id;
            }
        }

X-C. La modification

Modification
Sélectionnez
 private void btnUpdate_Click(object sender, EventArgs e)
        {
            try
            {
                unclient = new clientmetier();
                unclient.id = (int)listView1.SelectedItems[0].Tag; //Récupération de l'identifiant
                unclient.nom = txtnom.Text;
                unclient.prenom = txtprenom.Text;
                unclient.tel = txttel.Text;
                unclient.adresse = txtadresse.Text;
                unclient.Updateclient();
                cleanfields();
                //Rafraichissement
                loaddata();
            }
            catch (Exception ex)
            {
                MessageBox.Show("Erreur vérifiez les champs SVP "+ex.Message);
            }
        }

X-D. La suppression

Suppression
Sélectionnez
 private void btnDelete_Click(object sender, EventArgs e)
        {
            clientmetier unclient = new clientmetier();
            try
            {
                unclient.id = (int)listView1.SelectedItems[0].Tag; //Récupération de l'identifiant
                unclient.Deleteclient(unclient.id); //Suppression
                cleanfields();
                //Rafraichissement
                loaddata();
            }
            catch (Exception ex)
            {
                MessageBox.Show("Aucune sélection effectuée");
            }
        }

XI. Remerciements

Je voudrais remercier mon professeur Monsieur Innocent Apkatou, tous les membres du site en particulier djibril, Lana.Bauer, Viduc, ClaudeLELOUP et f-leb.

Vous avez aimé ce tutoriel ? Alors partagez-le en cliquant sur les boutons suivants : Viadeo Twitter Facebook Share on Google+   

  

Les sources présentées sur cette page sont libres de droits et vous pouvez les utiliser à votre convenance. Par contre, la page de présentation constitue une œuvre intellectuelle protégée par les droits d'auteur. Copyright © 2014 landry161. 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'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.