IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C# Discussion :

Singleton pattern et problème de connexion à une DBSQL


Sujet :

C#

  1. #1
    Nouveau Candidat au Club
    Homme Profil pro
    Architecte de système d'information
    Inscrit en
    Juillet 2014
    Messages
    4
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Architecte de système d'information
    Secteur : Finance

    Informations forums :
    Inscription : Juillet 2014
    Messages : 4
    Points : 1
    Points
    1
    Par défaut Singleton pattern et problème de connexion à une DBSQL
    Bonjour a tous, je bloque un peu dans un programme qui créé un addin excel (via excel-DNA, mais normalement ca ca va), pour aller requeter sur une DB. je souhaite utiliser le pattern du singleton pour faire mes connecxons, mais je ne vois pas comment structurer mon code (ou placer la connection). Si vous pouviez m'aider ca serait vraiment cool.
    Voila ma fonction d'appel :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    namespace ClassLibrary
    {
        public class MyFunctions
            {
     
            [ExcelFunction(Description = "fonction de recherche")]
            public static double id(string _isin)
                //module excel
            {
     
                double res;
     
                //res= "id= " + B.getID(_isin);
                res = DBSQL.Instance.getID(_isin);
     
                return res;
            }
        }
     
    }


    et voila la class ou je bug :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
     
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Data.SqlClient;
     
     
     
     
     
    namespace AccesDB
    {
        public class DBSQL : iAccesDB1
        {
            private SqlConnection MaConn = new SqlConnection("ezklhfgpiqhgbfozhg");
     
            private static volatile DBSQL instance;
            private static object syncRoot = new Object();
     
            private DBSQL() {}
     
            public static DBSQL Instance
            {
                get
                {
                    if (instance == null)
                    {
                        lock (syncRoot)
                        {
                            if (instance == null)
     
                                instance = new DBSQL();
                        }
                    }
                    return instance;
                 }
     
            }
     
     
            public void Connection()
            {
                MaConn.Open();
            }
     
            public void CloseConnection()
            {
                MaConn.Close();
            }
     
     
            public double getID(String _isin)
            {
                SqlDataReader rd;
                double res = -9999;
     
     
                SqlCommand cd = new SqlCommand("select cpn from tbassetOLD where isin='" + _isin + "'", MaConn);
     
                try
                {
                    rd = cd.ExecuteReader();
     
                    if (rd.HasRows)
                    {
                        while (rd.Read())
                            res = double.Parse(rd["cpn"].ToString());
                    }
     
     
                }
                catch (Exception ex)
                {
                    throw new Exception("1000: " + ex.Message);
                }
     
                return res;
     
            }
     
     
        }
    }
    Merci a tous !

  2. #2
    Membre éprouvé
    Homme Profil pro
    Architecte technique
    Inscrit en
    Septembre 2005
    Messages
    462
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Maine et Loire (Pays de la Loire)

    Informations professionnelles :
    Activité : Architecte technique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 462
    Points : 1 056
    Points
    1 056
    Par défaut
    Salut,

    Je ne vois pas précisément ton problème donc petit exemple.

    Ma classe qui implémente le "pattern singleton" :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
        public class TestSingleton
        {
            public int Compteur { get; private set; }
     
            private static TestSingleton current;
     
            public static TestSingleton Current
            {
                get
                {
                    return current ?? (current = new TestSingleton());
                }
            }
     
            private TestSingleton()
            {
                Compteur = 0;
            }
     
            public void AddCompteur()
            {
                Compteur++;
            }
        }
    Mon programme qui l'utilise :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
                var testSingleton1 = TestSingleton.Current;
                Console.WriteLine("testSingleton1.AddCompteur()");
                testSingleton1.AddCompteur();
                var testSingleton2 = TestSingleton.Current;
                Console.WriteLine("testSingleton1.Compteur : {0}", testSingleton1.Compteur);
                Console.WriteLine("testSingleton2.Compteur : {0}", testSingleton2.Compteur);
                Console.WriteLine("testSingleton2.AddCompteur()");
                testSingleton2.AddCompteur();
                Console.WriteLine("testSingleton1.Compteur : {0}", testSingleton1.Compteur);
                Console.WriteLine("testSingleton2.Compteur : {0}", testSingleton2.Compteur);
                Console.ReadLine();
     
                //Résultat :
                //testSingleton1.AddCompteur()
                //testSingleton1.Compteur : 1
                //testSingleton2.Compteur : 1
                //testSingleton2.AddCompteur()
                //testSingleton1.Compteur : 2
                //testSingleton2.Compteur : 2

  3. #3
    Nouveau Candidat au Club
    Homme Profil pro
    Architecte de système d'information
    Inscrit en
    Juillet 2014
    Messages
    4
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Architecte de système d'information
    Secteur : Finance

    Informations forums :
    Inscription : Juillet 2014
    Messages : 4
    Points : 1
    Points
    1
    Par défaut
    Je comprends à peu près ton exemple (je suis pas très au point), tu créé ton singleton et tu le rappelle dans ton programme.
    Sur mon exemple, j'appelle une fonction, qui est dans une classe ou il y a le singleton et la connexion à la DB. En fait je crois que je ne comprends pas ou je dois placer les procédures de connection: a part, après le res=instance ?
    Je ne vois pas pourquoi mon truc ne marche pas en fait et c'est horrible :-)

  4. #4
    Membre éprouvé
    Homme Profil pro
    Architecte technique
    Inscrit en
    Septembre 2005
    Messages
    462
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Maine et Loire (Pays de la Loire)

    Informations professionnelles :
    Activité : Architecte technique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 462
    Points : 1 056
    Points
    1 056
    Par défaut
    Je vois quelques petites "faille"...

    Par exemple dans ta méthode "getID" je ne te vois jamais ouvrir ta connexion.
    N'hésite pas à dire ce qu'il ne te va pas...


    Une connexion doit être ouverte la plus tard possible et fermée le plus tôt possible... L'idéal est de l'ouvrir juste avant d'effectuer ta requête ! et la refermé juste après...
    Par exemple je pense que c'est à ta classe d'ouvrir et fermer les connexions...

  5. #5
    Nouveau Candidat au Club
    Homme Profil pro
    Architecte de système d'information
    Inscrit en
    Juillet 2014
    Messages
    4
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Architecte de système d'information
    Secteur : Finance

    Informations forums :
    Inscription : Juillet 2014
    Messages : 4
    Points : 1
    Points
    1
    Par défaut
    merci pour ta réponse. alors en fait c'est un peu ca mon problème : je ne vois pas quand établir ma connection :je la met en dehors du pattern ? ou je la met juste avant ma fonction excel... En fait je ne comprends pas vraiment ce système de singleton.
    Concernant le moment de la connexion, vu qu'il peut y avoir 100 fonctions excel (la j'en ai mis qu'une seule), je me dis que ouvrir ma connection, puis balancer mes requètes (quitte à mettre un pool plus tard s'il y a trop d'utilisateurs), puis fermer la connection ca peut aller.
    Après je vais tenter de gérer le cache pour éviter des requètes inutiles.
    Du coup tu mettrais ou la connection toi ?
    Merrci de ton aide en tous cas, ca m'aide à comprendre.

  6. #6
    Membre éprouvé
    Homme Profil pro
    Architecte technique
    Inscrit en
    Septembre 2005
    Messages
    462
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Maine et Loire (Pays de la Loire)

    Informations professionnelles :
    Activité : Architecte technique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 462
    Points : 1 056
    Points
    1 056
    Par défaut
    Si on applique le principe Objet : SRP (Single responsibility principle) qui est : une classe doit avoir une et une seule responsabilité
    On peut dire que ta classe "DBSQL" a pour responsabilité de lire les données en base. C'est donc à elle d'ouvrir et fermer les connexions.
    J'espère que tu comprends l'idée... Car résumé des principes en quelques lignes n'est pas évident...

    Voici un petit tuto vidéo qui utilise ADO.NET/Singleton (La partie 1 & 2 pourrait t'intersser) : Accéder aux données ADO.NET, Entity Framework et WCF

    Voici ta classe avec quelques modifications :
    - using sur SqlCommand (libérer la mémoire [Appelle de la méthode "Dispose" de SqlCommand ).
    - Ouverture et fermeture de connexion en "privé".
    Code :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
        public class DBSQL : iAccesDB1
        {
            private SqlConnection _maConn;
            private static volatile DBSQL instance;
     
            private DBSQL()
            {
                _maConn = new SqlConnection("ezklhfgpiqhgbfozhg");
            }
     
            public static DBSQL Instance
            {
                get
                {
                    return instance ?? (instance = new DBSQL());
                }
            }
     
            private void Connection()
            {
                _maConn.Open();
            }
     
            private void CloseConnection()
            {
                _maConn.Close();
            }
     
     
            public double getID(String _isin)
            {
                SqlDataReader rd;
                double res = -9999;
     
     
                using (SqlCommand cd = new SqlCommand("select cpn from tbassetOLD where isin='" + _isin + "'", _maConn))
                {
                    try
                    {
                        Connection();
                        rd = cd.ExecuteReader();
     
                        if (rd.HasRows)
                        {
                            while (rd.Read())
                                res = double.Parse(rd["cpn"].ToString());
                        }
                        CloseConnection();
     
                    }
                    catch (Exception ex)
                    {
                        throw new Exception("1000: " + ex.Message);
                    }
                    finally
                    {
                        CloseConnection();
                    }
                }
     
                return res;
     
            }
        }

  7. #7
    Nouveau Candidat au Club
    Homme Profil pro
    Architecte de système d'information
    Inscrit en
    Juillet 2014
    Messages
    4
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Architecte de système d'information
    Secteur : Finance

    Informations forums :
    Inscription : Juillet 2014
    Messages : 4
    Points : 1
    Points
    1
    Par défaut
    ok je regarde ce que tu m'as envoyé,
    merci encore. (je comprends les concepts de classe, mais en fait je ne comprends pas le concept du singleton (en gros on m'a fait un brief en me disant que le singleton était une connection qu'on créait puis détruisait...) bref je n'ai rien compris. Je vais me pencher sur ton tuto et le singleton et ca devrait le faire. :-)

  8. #8
    Membre éprouvé
    Homme Profil pro
    Architecte technique
    Inscrit en
    Septembre 2005
    Messages
    462
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Maine et Loire (Pays de la Loire)

    Informations professionnelles :
    Activité : Architecte technique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 462
    Points : 1 056
    Points
    1 056
    Par défaut
    J'ai poussé mon premier exemple un peu plus loin. J'ai remis mon constructeur en "public" ce qui me permet d'instancier ma classe "Singleton" sans utiliser le mécanique d'instance unique (Singleton).
    Dans mon exemple on voit bien que quand j’exécute la méthode "AddCompteur", cette méthode impacte mes objets qui utilise l'instance unique.
    Si tu lance mon exemple dans une console je pense que tu comprendra assez vite le principe :
    testSingleton1 et testSingleton2 utilisent une instance unique alors que testNoSingleton3 non...

    Classe :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
        public class TestSingleton
        {
            public int Compteur { get; private set; }
     
            private static TestSingleton current;
     
            public static TestSingleton Current
            {
                get
                {
                    return current ?? (current = new TestSingleton());
                }
            }
     
            public TestSingleton()
            {
                Compteur = 0;
            }
     
            public void AddCompteur()
            {
                Compteur++;
            }
        }
    Utilisation :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
                Console.WriteLine("testSingleton1 = TestSingleton.Current");
                var testSingleton1 = TestSingleton.Current;
                Console.WriteLine("testSingleton1.AddCompteur()");
                testSingleton1.AddCompteur();
                Console.WriteLine("testSingleton2 = TestSingleton.Current");
                var testSingleton2 = TestSingleton.Current;
                Console.WriteLine("testSingleton1.Compteur : {0}", testSingleton1.Compteur);
                Console.WriteLine("testSingleton2.Compteur : {0}", testSingleton2.Compteur);
                Console.WriteLine("testSingleton2.AddCompteur()");
                testSingleton2.AddCompteur();
                Console.WriteLine("testSingleton1.Compteur : {0}", testSingleton1.Compteur);
                Console.WriteLine("testSingleton2.Compteur : {0}", testSingleton2.Compteur);
     
                Console.WriteLine("--------------------------------------------------------------");
     
                Console.WriteLine("testNoSingleton3 = new TestSingleton()");
                var testNoSingleton3 = new TestSingleton();
                Console.WriteLine("testSingleton1.Compteur : {0}", testSingleton1.Compteur);
                Console.WriteLine("testSingleton2.Compteur : {0}", testSingleton2.Compteur);
                Console.WriteLine("testNoSingleton3.Compteur : {0}", testNoSingleton3.Compteur);
     
                Console.WriteLine("testSingleton1.AddCompteur()");
                testSingleton1.AddCompteur(); //ou testSingleton2.AddCompteur();
                Console.WriteLine("testSingleton1.Compteur : {0}", testSingleton1.Compteur);
                Console.WriteLine("testSingleton2.Compteur : {0}", testSingleton2.Compteur);
                Console.WriteLine("testNoSingleton3.Compteur : {0}", testNoSingleton3.Compteur);
     
                Console.WriteLine("testNoSingleton3.AddCompteur()");
                testNoSingleton3.AddCompteur();
                Console.WriteLine("testSingleton1.Compteur : {0}", testSingleton1.Compteur);
                Console.WriteLine("testSingleton2.Compteur : {0}", testSingleton2.Compteur);
                Console.WriteLine("testNoSingleton3.Compteur : {0}", testNoSingleton3.Compteur);
                Console.ReadLine();

  9. #9
    Membre confirmé
    Profil pro
    Inscrit en
    Juin 2002
    Messages
    332
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations forums :
    Inscription : Juin 2002
    Messages : 332
    Points : 502
    Points
    502
    Par défaut
    Personnellement, ça fait des années que je n'ai pas eu à implémenter le pattern singleton manuellement. J'utilise pour cela le lifestyle de l'enregistrement de mon type dans Windsor Castle (tu pourrais utiliser Unity, Ninject, etc.).

    http://docs.castleproject.org/Defaul...ookieSupport=1

  10. #10
    Membre éprouvé
    Homme Profil pro
    Architecte technique
    Inscrit en
    Septembre 2005
    Messages
    462
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Maine et Loire (Pays de la Loire)

    Informations professionnelles :
    Activité : Architecte technique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 462
    Points : 1 056
    Points
    1 056
    Par défaut
    Citation Envoyé par Babyneedle Voir le message
    Personnellement, ça fait des années que je n'ai pas eu à implémenter le pattern singleton manuellement. J'utilise pour cela le lifestyle de l'enregistrement de mon type dans Windsor Castle (tu pourrais utiliser Unity, Ninject, etc.).
    On est d'accord mais avant d'utiliser "l'injection de dépendance", il est préférable de maîtriser les patterns...

  11. #11
    Expert confirmé
    Avatar de Pragmateek
    Homme Profil pro
    Formateur expert .Net/C#
    Inscrit en
    Mars 2006
    Messages
    2 635
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Formateur expert .Net/C#
    Secteur : Conseil

    Informations forums :
    Inscription : Mars 2006
    Messages : 2 635
    Points : 4 062
    Points
    4 062
    Par défaut
    L'exemple de katkiller est très bien.

    Juste une coquille : le CloseConnection() n'a pas à être fait à la fin du try, juste dans le finally.
    Sinon si tout va bien on ferme deux fois ce qui pourrait avoir des effets de bord...
    Formateur expert .Net/C#/WPF/EF Certifié MCP disponible sur Paris, province et pays limitrophes (enseignement en français uniquement).
    Mon blog : pragmateek.com

Discussions similaires

  1. [ODBC] [DB2] Problème de connexion à une base de données sur un as400 via PHP sous Linux
    Par boo64 dans le forum PHP & Base de données
    Réponses: 16
    Dernier message: 19/04/2006, 09h51
  2. [MySQL] Problème de connexion à une base...
    Par budiste dans le forum PHP & Base de données
    Réponses: 5
    Dernier message: 12/04/2006, 11h58
  3. Réponses: 4
    Dernier message: 24/02/2006, 10h48
  4. Réponses: 2
    Dernier message: 18/01/2006, 11h44
  5. Problème de connexion à une base access
    Par caco19 dans le forum ASP
    Réponses: 4
    Dernier message: 13/08/2004, 16h19

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo