web-dev-qa-db-fra.com

"ouvrir/fermer" SqlConnection ou rester ouvert?

Ma logique métier est implémentée dans des classes statiques simples avec des méthodes statiques. Chacune de ces méthodes ouvre/ferme la connexion SQL lorsqu'elle est appelée:

public static void DoSomething(string something)
{
    using (SqlConnection connection = new SqlConnection("..."))
    {
        connection.Open();

        // ...

        connection.Close();
    }
}

Mais je pense qu'éviter d'ouvrir et de fermer une connexion économise les performances . J'ai fait quelques tests il y a longtemps avec OleDbConnection class (je ne suis pas sûr de SqlConnection), et cela a certainement aidé à fonctionner comme ça (autant que je me souvienne):

//pass the connection object into the method
public static void DoSomething(string something, SqlConnection connection)
{
    bool openConn = (connection.State == ConnectionState.Open);
    if (!openConn)
    {
        connection.Open();
    }

    // ....

    if (openConn) 
    {
        connection.Close();
    }
}

La question est donc: devrais-je choisir la méthode (a) ou la méthode (b)? J'ai lu sur une autre question de stackoverflow que la mise en commun des connexions m'a sauvé les performances, je n'ai pas à m'en soucier du tout ...

PS. C'est une application ASP.NET - les connexions n'existent que pendant une requête Web. Pas une application ou un service gagnant.

97
Alex

s'en tenir à l'option a

Le regroupement de connexions est votre ami.

71
Adriaan Stander

Utilisez la méthode (a) à chaque fois. Lorsque vous commencez à mettre à l'échelle votre application, la logique qui traite de l'état deviendra un réel problème si vous ne le faites pas.

Le regroupement de connexions fait ce qu'il dit sur l'étain. Il suffit de penser à ce qui se passe lorsque l’application évolue et à la difficulté de gérer manuellement l’état ouvert/fermé de la connexion. Le pool de connexions fait un excellent travail de gestion automatique de cela. Si les performances vous inquiètent, pensez à un mécanisme de cache mémoire afin que rien ne soit bloqué.

72
WeNeedAnswers

Fermez toujours les connexions dès que vous en avez terminé, afin que la connexion à la base de données sous-jacente puisse revenir dans le pool et être disponible pour les autres appelants. Le regroupement de connexions est assez bien optimisé, il n'y a donc pas de pénalité notable pour cela. Le conseil est fondamentalement le même que pour les transactions - gardez-les courtes et proches lorsque vous avez terminé.

Cela devient plus compliqué si vous rencontrez des problèmes MSDTC en utilisant une seule transaction autour du code qui utilise plusieurs connexions. Dans ce cas, vous devez réellement partager l'objet de connexion et ne le fermer que lorsque la transaction est terminée.

Cependant, comme vous le faites ici à la main, vous pouvez explorer des outils qui gèrent les connexions pour vous, tels que DataSets, Linq to SQL, Entity Framework ou NHibernate.

28
Neil Barnwell

Disclaimer: Je sais que c'est vieux, mais j'ai trouvé un moyen facile de démontrer ce fait, alors je mets mes deux sous.

Si vous avez du mal à croire que la mise en commun va vraiment être plus rapide, essayez ceci:

Ajouter le suivant quelque part:

using System.Diagnostics;
public static class TestExtensions
{
    public static void TimedOpen(this SqlConnection conn)
    {
        Stopwatch sw = Stopwatch.StartNew();
        conn.Open();
        Console.WriteLine(sw.Elapsed);
    }
}

Maintenant, remplacez tous les appels à Open() par TimedOpen() et exécutez votre programme. Désormais, pour chaque chaîne de connexion distincte que vous avez, la fenêtre de la console (sortie) aura une seule longue ouverture, et un groupe de very fast s'ouvrira.

Si vous voulez les étiqueter, vous pouvez ajouter new StackTrace(true).GetFrame(1) + à l'appel à WriteLine.

12
Crisfole

Il existe des distinctions entre les connexions physiques et logiques. DbConnection est un type de connexion logique et utilise une connexion physique sous-jacente à Oracle. Fermer/ouvrir DbConnection n'affecte pas vos performances, mais rend votre code propre et stable - les fuites de connexion sont impossibles dans ce cas.

Vous devez également vous rappeler les cas où il existe des limitations pour les connexions parallèles sur un serveur de base de données - en tenant compte de cela, il est nécessaire de rendre vos connexions très courtes.

Le pool de connexions vous libère de la vérification de l'état de la connexion - il suffit de les ouvrir, de les utiliser et de les fermer immédiatement.

7
Tony Kh

Normalement, vous devriez garder une connexion pour chaque transaction (aucun calcul en parallèle)

par exemple, lorsque l'utilisateur exécute une action de charge, votre application doit d'abord trouver le solde de l'utilisateur et le mettre à jour, elle doit utiliser la même connexion.

Même si ado.net a son pool de connexions, le coût de la distribution est très faible, mais la réutilisation de la connexion est un meilleur choix.

Pourquoi ne pas garder qu'une seule connexion en application

Étant donné que la connexion est bloquante lorsque vous exécutez une requête ou une commande, Cela signifie donc que votre application effectue uniquement une opération de base de données à sametime, Les performances sont médiocres.

Un autre problème est que votre application aura toujours une connexion, même si votre utilisateur ne l'ouvre que, mais aucune opération. Si plusieurs utilisateurs ouvrent votre application, le serveur de base de données coûtera bientôt toute la source de connexion, n'importe quoi.

0
ShiningRush