Je veux clarifier cette situation.
Selon les directives de Microsoft, il est recommandé de fournir une Close
méthode le cas échéant. Voici une citation des directives de conception du cadre
Envisagez de fournir une méthode Close()
, en plus de la Dispose()
terminologie standard, si close est dans le domaine. Ce faisant, il est important de rendre l' Close
implémentation identique à Dispose
...
Dans la plupart des cas Close
, les Dispose
méthodes sont équivalentes. La principale différence entre Close
et Dispose
dans le cas de SqlConnectionObject
est:
Une application peut appeler Close
plusieurs fois. Aucune exception n'est générée.
Si vous avez appelé la Dispose
méthode
SqlConnection
, l'état de l'objet sera réinitialisé. Si vous essayez d'appeler une méthode sur un SqlConnection
objet supprimé , vous recevrez une exception.
Cela dit:
- Si vous utilisez un objet de connexion une fois, utilisez
Dispose
.
- Si l'objet de connexion doit être réutilisé, utilisez la
Close
méthode.
con.Open() con.Close();
2con.Open(); // reuse
3.con.Dispose(); // use one time con.Open(); // error
Comme d'habitude, la réponse est: cela dépend. Différentes classes sont implémentées
IDisposable
de différentes manières, et c'est à vous de faire les recherches nécessaires.Pour autant
SqlClient
, la pratique recommandée est de faire ce qui suit:Vous devriez appeler
Dispose
(ouClose
*) sur la connexion! N'attendez pas que le ramasse-miettes nettoie votre connexion, cela bloquera les connexions dans le pool jusqu'au prochain cycle GC (au moins). Si vous appelezDispose
, il n'est pas nécessaire d'appelerClose
, et comme lausing
construction le rend si facile à gérerDispose
correctement, il n'y a vraiment aucune raison d'appelerClose
.Les connexions sont automatiquement regroupées et l'appel
Dispose
/Close
sur la connexion ne ferme pas physiquement la connexion (dans des circonstances normales). N'essayez pas de mettre en œuvre votre propre regroupement.SqlClient
effectue le nettoyage de la connexion lorsqu'elle est extraite du pool (comme la restauration du contexte de la base de données et des options de connexion).* si vous appelez
Close
, assurez-vous de le faire d'une manière sûre pour les exceptions (c'est-à-dire dans un bloc catch ou enfin).la source
conn.Close(); // Optional
ce n'est pas facultatif. C'est redondant et inutile. Vous supprimez l'objet deux fois et cela sera marqué comme un avertissement par certains outils d'analyse de code.using (var x = ..) { x.Dispose(); }
, auquel casx
est vraiment "disposé deux fois".Vous devez appeler Dispose ()!
Dispose () est pour le développeur à appeler, le Garbage Collector appelle Finalize (). Si vous n'appelez pas Dispose () sur vos objets, les ressources non gérées qu'ils ont utilisées ne seront pas supprimées tant que le garbage collector ne viendra pas et n'appellera pas finalize sur eux (et qui sait quand cela se produira).
Ce scénario est appelé Finalisation non déterministe et est un piège courant pour les développeurs .net. Si vous travaillez avec des objets qui implémentent IDisposable, appelez Dispose () sur eux!
http://www.ondotnet.com/pub/a/oreilly/dotnet/news/programmingCsharp_0801.html?page=last
Bien qu'il puisse y avoir de nombreuses instances (comme sur SqlConnection) où vous appelez Disponse () sur un objet et qu'il appelle simplement Close () sur sa connexion ou ferme un descripteur de fichier, il est presque toujours préférable d'appeler Dispose ()! sauf si vous prévoyez de réutiliser l'objet dans un avenir très proche.
la source
Dispose
.Dispose()
si vous n'utilisez pasusing()
avec une classe qui implémenteIDisposable
. Si la classe appelée implémente IDisposable et que vous avez enveloppé son utilisation sur la page à l'intérieurusing()
, vous pouvez vous en débarrasser avec leDispose()
(jeu de mots prévu, alors tirez-moi). L'utilisationClose()
, cependant, est recommandée avec tout ce qui utilise explicitementOpen()
AFAIK.Close
la connexion établie, Postgres définit automatiquement l'identifiant de connexion surnull
. A partir de là, on ne peut plusDispose
un identifiant de connexion sql qui est déjà défini surnull
.Car
SqlConnection
, du point de vue de la connexion elle-même, ils sont équivalents. Selon Reflector, lesDispose()
appelsClose()
ainsi que quelques opérations supplémentaires de libération de mémoire, principalement en définissant des membres égaux à null.Pour Stream, ils sont en fait équivalents.
Stream.Dispose()
appelle simplement Close ().la source
Component
ce qui ne semble rien faire pour essayer d'appelerClose()
. Je ne vois nulle partDBConnection
ouSqlConnection
qui est lié à l'une de ces notifications. Il a cependant un privéDisposeMe()
qui n'est référencé nulle part .Ce conseil rapide potentiel est devenu une longue réponse. Désolé.
Comme l'a souligné Tyler dans sa belle réponse, l'appel
Dispose()
est une excellente pratique de programmation. C'est parce que cette méthode est censée «rassembler» toutes les ressources nécessaires pour libérer des ressources afin qu'il n'y ait pas de ressources ouvertes inutiles. Si vous avez écrit du texte dans un fichier, par exemple, et que vous n'avez pas réussi à fermer le fichier (libérer la ressource), il restera ouvert et personne d'autre ne pourra y écrire jusqu'à ce que le GC arrive et fasse ce que vous devriez avoir terminé.Maintenant, dans certains cas, il y aura des méthodes de "finalisation" plus spécifiques à la classe avec laquelle vous avez affaire, comme
StreamWriter.Close()
, qui remplaceTextWriter.Close()
. En effet, ils sont généralement plus adaptés à la situation: un StreamWriterClose()
, par exemple, vide le flux et l'encodeur sous-jacent avant la créationDispose()
de l'objet! Cool!Cependant, en parcourant MSDN, vous constaterez que même Microsoft est parfois confus par la multitude de fermetures et de disposers. Dans cette page Web , par exemple, dans certains exemples, il
Close()
est appelé avant l'impliciteDispose()
(voir l' instruction using si vous ne comprenez pas pourquoi c'est implicite), et dans un en particulier, ils ne se soucient pas. Pourquoi cela serait-il? Moi aussi, j'étais perplexe.La raison pour laquelle j'ai pensé (et, je le souligne, il s'agit d' une recherche originale et je pourrais sûrement perdre ma réputation si je me trompe) est que cela
Close()
pourrait échouer, ce quiDispose()
donnerait une exception tout en laissant les ressources ouvertes, tout en les libérant sûrement . C'est pourquoi unDispose()
devrait toujours sauvegarder unClose()
appel (désolé pour le jeu de mots).Et oui, je suppose que Microsoft a glissé sur cet exemple. Peut-être que cet horodatage ne serait jamais vidé dans le fichier.
Je corrige mon ancien code demain.
Edit: désolé Brannon, je ne peux pas commenter votre réponse, mais êtes-vous sûr que c'est une bonne idée d'appeler
Close()
sur unfinally
bloc? Je suppose qu'une exception à cela pourrait ruiner le reste du bloc, qui contiendrait probablement un code de nettoyage important.Réponse à Brannon: super, n'oubliez pas d'appeler
Close()
quand c'est vraiment nécessaire (par exemple lorsque vous traitez avec des flux - je ne sais pas grand-chose sur les connexions SQL dans .NET).la source
Tapez sur iDisposable et appelez disposer à ce sujet. Cela invoquera la méthode configurée pour implémenter "iDisposable.Dispose", quel que soit le nom de la fonction.
la source
IDisposable.Dispose
, mais cela ne signifie pas que c'est le nom. Notez que dans vb.net, il est possible qu'une fonction soit liée à plusieurs membres d'interface avec des noms qui n'ont pas besoin d'être liés à celui de la fonction.using (myObj as IDisposable)
En général, nous sommes confrontés à un problème dans Close (), Abort () et Dispose (), mais laissez-moi vous dire la différence entre eux.
1) ABORT: - Je ne suggérerai pas de l'utiliser car lorsque l'abandon est appelé, le client supprimera la connexion sans en informer le serveur afin que le serveur attende pendant un certain temps (environ 1 min). Si vous avez une demande en masse, vous ne pouvez pas utiliser abort () car cela peut entraîner l'expiration de votre pool de connexions limité.
2) Fermer: - Fermer est un très bon moyen de fermer la connexion car lors de la fermeture de la connexion, il appellera le serveur et accusera le serveur de se fermer par ce côté également.
Ici, encore une chose à regarder. Dans certains cas, si une erreur se produit, ce n'est pas un bon moyen d'écrire enfin du code dans cette connection.close () car à ce moment-là, l'état de communication sera défaillant.
3) Éliminer: - C'est un type de fermeture, mais après avoir fermé la connexion, vous ne pouvez plus l'ouvrir.
Alors essayez de cette façon,
la source
client != null
est incorrecte / trompeuse car elle ne protège pas toutes les utilisations. De plus, je ne suis pas sûr de savoir comment le code peut atteindre l'état "cette connexion n'est pas ouverte et devrait être fermée".