À quel point est-ce mauvais de ne pas disposer () de SqlConnections?

14

Personnellement, j'éclate en ruches si je ne mets pas d'objets ADO qui implémentent IDisposable dans l'utilisation d'instructions. Mais dans mon contrat actuel, j'ai trouvé que leur code de fournisseur d'accès aux données interne à l'entreprise ne 1) implémente pas IDisposable et 2) appelle Dispose () sur tout ce qu'il utilise, à tout moment, jamais. Les utilisateurs se plaignent beaucoup des problèmes de performances dans les applications Winforms qui utilisent massivement ce cadre pour l'accès aux données, et bien qu'il y ait BEAUCOUP d'autres problèmes dans le code qui pourraient nuire aux performances, celui-ci me crie juste et est plus fruits plus bas que les autres.

Donc, au-delà de dire quelque chose comme «Dispose is there for a reason, use it», que puis-je dire à ces gens pour les convaincre que c'est vraiment, vraiment mauvais?

AJ Johnson
la source
5
Heh..my suppose que, à un moment donné, il ne sera pas nécessaire de convaincre :)
dr Hannibal Lecter

Réponses:

6

Je dirais que la meilleure chose que vous puissiez faire est de les signaler aux modèles et pratiques de Microsoft concernant Dispose() ici . Faites-leur voir toutes les conséquences de ne pas utiliser cet outil qui se trouve juste devant eux.

Jesse C. Slicer
la source
1
J'aimerais juste pouvoir trouver une version qui ne crie pas "c'est du contenu retiré" en haut.
AJ Johnson
Vous savez, mes yeux ont juste passé sous silence cela. Mais maintenant, en le lisant attentivement, je me demande quelles technologies les gens pourraient "encore utiliser" et qui sont retirées de cette page. Peut-être CAS?
Jesse C. Slicer
En le scannant de plus près, la plupart de cela me semble toujours pertinent. Je ne sais pas non plus pourquoi il est marqué retiré.
AJ Johnson
10

Si vous n'appelez pas la méthode Dispose sur une connexion SQL, lorsque vous avez fini de l'utiliser, cette connexion n'est PAS renvoyée au pool de connexions.

Si vous rencontrez des problèmes de performances, je suppose que le nombre maximal de connexions est ouvert sur votre base de données. Un DBA pourrait facilement le confirmer.

Les meilleures pratiques de Microsoft vous demandent de placer votre code de connexion dans une instruction Using, en vous assurant que la connexion est supprimée et que la connexion est retournée au pool.

Walter
la source
L'appel Closeest suffisant pour revenir au pool de connexions. La question ne dit pas que ce Closen'est pas explicitement utilisé.
user2864740
9

Le pool de connexions à la base de données est de taille limitée et s'il se remplit, les nouvelles connexions attendent que les anciennes connexions soient libérées. Si vous ne les éliminez pas dès que vous en avez fini avec eux, ils finiront par être libérés lorsque le finalisateur fonctionnera, mais c'est une durée indéterminée à l'avenir ... Donc, au mieux, vous allez voir de longs délais lors de l'ouverture de nouvelles connexions.

Au pire, ils ont peut-être désactivé le pool de connexions. Peut-être ont-ils découvert qu'après un certain temps, leur application renvoyait des erreurs de "délai d'attente pour la connexion" et désactivait le pool de connexions "résolvait" ce problème. Cependant, c'est bien pire car cela signifie que vous créez une toute nouvelle connexion à chaque fois - ce qui est étonnamment gourmand en ressources. Si vous avez ouvert des centaines de connexions à la base de données, il n'est pas étonnant que vous rencontriez des problèmes de performances.

La bonne façon de résoudre tous ces problèmes est de supprimer votre connexion dès que vous en avez terminé. La meilleure idée est de maintenir la connexion ouverte aussi longtemps que nécessaire, et non plus.

Dean Harding
la source
1
C'est même un peu pire que ça. Si le pool est suffisamment sauvegardé, de nombreuses tentatives de connexion échoueront finalement, y compris les tentatives de connexion à partir d'outils de gestion, et vous pouvez effectivement vous verrouiller notre base de données.
Joel Coehoorn
3

Dans toute application sérieuse, je dirais que c'est assez mauvais. Non seulement laisser ces objets flotter autour de tuer les performances, il est également tout simplement non professionnel. La bonne nouvelle est que Microsoft implémente Finalize dans la hiérarchie des objets.

~Object()
{
    this.Dispose(false);    
}

public void Dispose()
{
    this.Dispose(true);
    GC.SuppressFinalize(this);
}

protected virtual void Dispose(bool disposing)
{
    // ...
}

Prenez System.Data.SqlClient.SqlConnectionpar exemple:

System.ComponentModel.Component <- Implémente le modèle d'élimination Finalize.
    |
System.Data.Common.DbConnection
    |
System.Data.SqlClient.SqlConnection

Les objets seront finalement éliminés mais la nature non déterministe fait des ravages sur les performances.

ChaosPandion
la source
0

Eh bien, pour commencer, vous n'arrêtez pas la connexion. Il doit donc soit a) être abandonné automatiquement, soit b) être parcouru et mis à jour même si le client n'a aucune utilité.

Je suppose que b) en raison de la performance que vous décrivez. Cependant, ce n'est probablement pas la seule raison.

Vous DEVEZ fermer vos connexions, de préférence côté client, mais vous devez également implémenter une sécurité intégrée côté serveur. Sinon, vous avez juste plus de conneries que votre serveur de base de données doit traiter jusqu'à ce qu'il soit publié à Dieu sait quand.


la source