Est-il nécessaire de fermer / supprimer un SqlDataReader si vous fermez déjà SqlConnection?

J’ai remarqué cette question , mais ma question est un peu plus précise.

Y at-il un avantage à utiliser

using (SqlConnection conn = new SqlConnection(conStr)) { using (SqlCommand command = new SqlCommand()) { // dostuff } } 

au lieu de

 using (SqlConnection conn = new SqlConnection(conStr)) { SqlCommand command = new SqlCommand(); // dostuff } 

Évidemment, si vous prévoyez d’exécuter plus d’une commande avec la même connexion est important, car fermer un SqlDataReader est plus efficace que fermer et rouvrir une connexion (appeler conn.Close();conn.Open(); libérera également la lien).

Je vois beaucoup de gens insister sur le fait que ne pas fermer SqlDataReader signifie laisser des ressources de connexion ouvertes, mais cela ne s’applique-t-il pas uniquement si vous ne fermez pas la connexion?

À mon avis, il y a deux règles à suivre ici:

  1. Les classes qui implémentent IDisposable doivent être encapsulées dans un bloc using .
  2. Vous ne devez pas compter sur l’implémentation d’IDisposable par une classe pour ignorer la règle 1.

Autrement dit, même si vous savez que la suppression de l’object de connexion a pris en charge la suppression de son object de commande associé, vous ne devez pas vous fier à ce comportement.

À propos, il est possible d’imbriquer des blocs de manière plus propre:

 using (SqlConnection conn = new SqlConnection(conStr)) using (SqlCommand command = new SqlCommand()) { // dostuff } 

et j’utiliserais

 SqlCommand command = conn.CreateCommand(); 

au lieu de créer un nouveau SqlCommand et de l’associer ensuite à la connexion.

Techniquement, ce n’est pas nécessaire. la fermeture d’un SqlConnection devrait détruire toutes les ressources SqlDataReader . L’inverse est également vrai; vous n’avez pas besoin de Dispose la SqlConnection si vous disposez d’un SqlDataReader créé avec CommandBehavior.CloseConnection .

En pratique , cependant, quand une classe implémente IDisposable , vous devriez la Dispose quand vous en aurez fini. Les détails d’implémentation des classes d’infrastructure sont sujets à modification à tout moment, et à moins que la documentation n’indique spécifiquement les circonstances dans lesquelles il n’est pas nécessaire d’ Dispose l’instance, il est toujours possible que des modifications / mises à jour futures entraînent une modification de votre code. fuite de ressources.

Ce n’est vraiment pas un effort supplémentaire – alors enveloppez-le simplement dans un bloc using .

Cela peut ne pas être nécessaire dans beaucoup de cas, mais c’est une bonne pratique pour une raison. Il n’y a aucune raison de laisser les ressources persister au-delà du point où elles ne sont plus utiles. La construction using aide à assurer cela.

N’est-ce pas simplement une question de libération de la ressource maintenant par rapport à la récupération de place libérée plus tard?

Il y a une différence. Si vous créez 2 de ces lecteurs sans ouvrir / fermer la connexion, mais que vous ne supprimez pas le premier avant d’utiliser le second, vous obtiendrez un conflit indiquant que la connexion est déjà associée à un lecteur ouvert.