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

Services Web Discussion :

Performances : connexion base de données persistante ou pas ? [Débutant]


Sujet :

Services Web

  1. #1
    Expert éminent
    Avatar de StringBuilder
    Homme Profil pro
    Chef de projets
    Inscrit en
    Février 2010
    Messages
    4 154
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Chef de projets
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2010
    Messages : 4 154
    Points : 7 403
    Points
    7 403
    Billets dans le blog
    1
    Par défaut Performances : connexion base de données persistante ou pas ?
    Bonjour,

    J'ai écrit un WebService en C# qui consomme des méthodes d'une classe statique qui permet d'accéder aux données.

    Par exemple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    public void DoSomething()
    {
         Data.DoFirstThing();
         Date.DoSecondThing();
    }
    Actuellement, dans ma classe Data, chaque méthode crée, ouvre et ferme une connexion à la base de données :
    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
     
        public static void NettoyerPartie(int partie_id)
        {
            using (SqlConnection cnx = new SqlConnection(CNX_STRING))
            {
                cnx.Open();
     
                using (SqlCommand cmd = cnx.CreateCommand())
                {
                    cmd.CommandText = "NettoyerPartie";
                    cmd.CommandType = CommandType.StoredProcedure;
                    cmd.Parameters.AddWithValue("partie_id", partie_id);
                    cmd.ExecuteNonQuery();
                }
     
                cnx.Close();
            }
        }
     
        static public Question TrouverMeilleureQuestion(int partie_id)
        {
            Question res = new Question();
            using (SqlConnection cnx = new SqlConnection(CNX_STRING))
            {
                cnx.Open();
     
                using (SqlCommand cmd = cnx.CreateCommand())
                {
                    cmd.CommandText = "TrouverMeilleureQuestion";
                    cmd.CommandType = CommandType.StoredProcedure;
                    cmd.Parameters.AddWithValue("partie_id", partie_id);
                    SqlParameter pid = cmd.Parameters.Add("question_id", SqlDbType.Int, 4);
                    SqlParameter pnom = cmd.Parameters.Add("question_nom", SqlDbType.VarChar, 50);
                    pid.Direction = ParameterDirection.Output;
                    pnom.Direction = ParameterDirection.Output;
                    cmd.ExecuteNonQuery();
                    res.id = (int)pid.Value;
                    res.nom = (string)pnom.Value;
                }
     
                cnx.Close();
            }
            return res;
        }
    J'imagine (j'espère) que C# et le pilote SQL Server comprend qu'il ne faut pas ouvrir et fermer "réellement" la base à chaque appel.
    Est-ce le cas ?

    Du coup, je pose une question :
    - Si je rends Data instanciable et que j'ouvre la connexion dans le constructeur et la ferme dans le Dispose(), je réduis le nombre d'ouvertures/fermetures. Cependant, cela veut dire si une méthode de mon WebService met longtemps entre deux appels aux méthodes de data, je conserve inutilement une connexion ouverte, ce qui va augmenter le nombre de connexion concurrentes dans la base ainsi que la charge mémoire. Est-ce que ce sera réellement plus rapide ?
    - Enfin, si je n'appelle plus directement SqlConnection mais un singleton qui me retourne une instance partagée de la connexion, vais-je y gagner quelque chose ? Est-ce que je ne risque pas d'avoir des problèmes de contexte entre deux appels au WebService (l'instance de mon singleton sera-t-elle partagée entre tous les appels à mon WebService) ?

    Afin d'améliorer les performances, je n'ai pas activé l'état de session sur le serveur.
    Une autre solution serait-elle de mettre la connexion en session ? Ou même en variable d'application ? Intérêt, risques ?
    On ne jouit bien que de ce qu’on partage.

  2. #2
    Membre émérite Avatar de meziantou
    Homme Profil pro
    Ingénieur R&D
    Inscrit en
    Avril 2010
    Messages
    1 223
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : Canada

    Informations professionnelles :
    Activité : Ingénieur R&D
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2010
    Messages : 1 223
    Points : 2 439
    Points
    2 439
    Par défaut
    J'imagine (j'espère) que C# et le pilote SQL Server comprend qu'il ne faut pas ouvrir et fermer "réellement" la base à chaque appel.
    C'est pour cela qu'il y a le Connection pooling : http://msdn.microsoft.com/fr-fr/libr...v=vs.110).aspx

  3. #3
    Modérateur
    Avatar de DotNetMatt
    Homme Profil pro
    CTO
    Inscrit en
    Février 2010
    Messages
    3 611
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : CTO
    Secteur : Finance

    Informations forums :
    Inscription : Février 2010
    Messages : 3 611
    Points : 9 743
    Points
    9 743
    Billets dans le blog
    3
    Par défaut
    C'est une très mauvaise idée d'utiliser un Singleton pour gérer les connexions à une base de données, surtout sur un environnement Web où par nature on fonctionne en multi-thread. En gros chaque requête s'exécute sur son propre thread.

    Donc si tu mets un Singleton, non seulement tu vas créer un goulet d'étranglement mais tu risques d'avoir beaucoup d'erreurs et de difficultés pour gérer tes connexions correctement.

    En utilisant ADO.NET, il y a un mécanisme appelé le Pool de connexions (Connection Pool) qui sait gérer les ouvertures/fermetures de connexions. La bonne pratique est donc de le laisser gérer ce genre de choses. Comment ça marche ?

    Lors du premier appel, il ouvre la connexion (ce qui est donc coûteux). Ensuite quand la connexion est fermée, ADO.NET ne détruit pas la connexion, il va créer un pool de connexion, et conserver une référence vers la connexion que tu viens de libérer. Lorsque ton application aura besoin d'une nouvelle connexion, alors le pool pourra piocher dans le stock de références, et renvoyer un objet connexion. Cela évite ainsi de devoir réellement ouvrir et fermer les connexions, c'est donc moins coûteux.

    Côté ASP.NET, la bonne pratique est d'ouvrir et fermer les connexions aussi rapidement que possible, mais certainement pas d'utiliser un Singleton.

    Si tu veux creuser un peu : ADO.NET Connection Pooling at a Glance ou encore Connection Pooling for the SQL Server DBA.
    Less Is More
    Pensez à utiliser les boutons , et les balises code
    Desole pour l'absence d'accents, clavier US oblige
    Celui qui pense qu'un professionnel coute cher n'a aucune idee de ce que peut lui couter un incompetent.

  4. #4
    Expert éminent
    Avatar de StringBuilder
    Homme Profil pro
    Chef de projets
    Inscrit en
    Février 2010
    Messages
    4 154
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Chef de projets
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2010
    Messages : 4 154
    Points : 7 403
    Points
    7 403
    Billets dans le blog
    1
    Par défaut
    Ok.

    Donc c'est bon, je suis pas trop rouillé, j'ai utilisé la bonne méthode.
    Je voulais juste être certain que depuis l'époque d'ASP (pas .NET) les best-practices n'avaient pas changé
    Merci pour le lien meziantou, il m'a confirmé qu'il n'y avait rien de particulier à mettre en place pour activer le pooling (à l'époque de SQL Server 7, il fallait bidouiller dans la connexion string de mémoire).

    Sinon, je suis surpris de ne voir aucun "cnx.Close()" dans les exemple.

    Sont-ils implicites en sortie du using {}, ou au contraire, dois-je les supprimer pour bien indiquer au pool que les connexion restent réutilisables ?

    Edit : Réponse trouvée dans le premier lien de DotNetMatt :
    The very first step that we should do is – Ensure that every connection that is opened, is closed explicitly. At times what happens is, we open the connection, perform the desired database operation, but we do not close the connection explicitly. Internally it cannot be used as an available valid connection from the pool. The application would have to wait for GC to claim it, until then it is not marked as available from the pool. In such case, even though you are not using max pool size number of connection simultaneously, you may get this error. This is the most probable cause of this issue.
    Ok, donc je laisse bien mes cnx.Close()
    On ne jouit bien que de ce qu’on partage.

  5. #5
    Modérateur
    Avatar de DotNetMatt
    Homme Profil pro
    CTO
    Inscrit en
    Février 2010
    Messages
    3 611
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : CTO
    Secteur : Finance

    Informations forums :
    Inscription : Février 2010
    Messages : 3 611
    Points : 9 743
    Points
    9 743
    Billets dans le blog
    3
    Par défaut
    Citation Envoyé par StringBuilder Voir le message
    Sont-ils implicites en sortie du using {}, ou au contraire, dois-je les supprimer pour bien indiquer au pool que les connexion restent réutilisables ?
    Oui c'est implicite, car le bloc using a pour vocation de libérer les objets via l'interface IDisposable. Donc en sortant du bloc using, la connexion sera fermée automatiquement.

    On peut assimiler le bloc using à un bloc try/catch/finally, la fermeture de la connexion et son "dispose" étant faits dans le finally, donc même en cas d'erreur.
    Less Is More
    Pensez à utiliser les boutons , et les balises code
    Desole pour l'absence d'accents, clavier US oblige
    Celui qui pense qu'un professionnel coute cher n'a aucune idee de ce que peut lui couter un incompetent.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 2
    Dernier message: 19/06/2009, 17h40
  2. Réponses: 5
    Dernier message: 07/04/2005, 14h12
  3. [Tomcat][Oracle] connexion base de donnes debutant....
    Par yogz dans le forum Tomcat et TomEE
    Réponses: 8
    Dernier message: 16/07/2004, 13h32
  4. [XMLRAD] Connexion Base de données Informix
    Par clisson dans le forum XMLRAD
    Réponses: 3
    Dernier message: 14/01/2003, 13h46
  5. connexion base de donné
    Par saidi dans le forum MFC
    Réponses: 3
    Dernier message: 07/08/2002, 22h22

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