2010-08-02 25 views
11

Je sais que j'ai posé une question connexe plus tôt. J'ai juste eu une autre pensée.en utilisant SQLDataReader

using (SqlConnection conn = new SqlConnection('blah blah')) 
{ 
    using(SqlCommand cmd = new SqlCommand(sqlStatement, conn)) 
    { 
     conn.open(); 

     // *** do I need to put this in using as well? *** 
     SqlDataReader dr = cmd.ExecuteReader() 
     { 
      While(dr.Read()) 
      { 
       //read here 
      } 
     } 
    } 
} 

L'argument est que: Puisque l'objet SqlDataReaderdr est pas un objet comme les objets de connexion ou de commande, son tout simplement une référence indiquant la méthode cmd.ExecuteReader(), dois-je mettre le lecteur dans un using. (Maintenant basé sur mon post précédent, je comprends que tout objet qui utilise IDisposable doit être mis dans un using, et SQLDataReader hérite de IDisposable, donc j'ai besoin de le mettre.Ai-je raison à mon avis?) Je suis juste confus puisque ce n'est pas un nouvel objet, cela causerait-il des problèmes pour disposer un objet qui est simplement un pointeur de référence à la commande?

Un grand merci

+0

"cmd.ExecuteReader" est une sorte de référence de la méthode. "cmd.ExecuteReader()" (entre crochets) est un appel de méthode. –

Répondre

26

Je pense que vous vous trompez. Le dr est une référence à l'objet renvoyé par cmd.ExecuteReader, qui va être un nouvel objet. Dans votre exemple, rien ne va se passer dr, donc oui, il doit être dans un using, ou être éliminé manuellement.

Votre jugement sur IDisposable implémenteurs ayant besoin de pour être dans un using est incorrect. Ils fonctionneront bien à l'extérieur. Une déclaration using est juste du sucre syntaxique pour un try ... finally. Les éléments qui implémentent IDisposable doivent être appelés Dispose, car ils signalent qu'ils doivent disposer d'un certain état de manière déterministe.

Notez que si vous n'appelez pas Dispose, ce n'est pas toujours un problème. Certains objets implémentent également le finaliseur, qui sera déclenché par le garbage collector. S'ils n'implémentent pas le finaliseur, ils peuvent laisser la mémoire non managée non récupérée. Cela restera non récupéré jusqu'à la fermeture de votre application. Toute la mémoire gérée est finalement récupérée, sauf si elle n'est pas éligible pour la récupération de place.

Réécrit:

using (SqlConnection conn = new SqlConnection('blah blah')) 
using(SqlCommand cmd = new SqlCommand(sqlStatement, conn)) 
{ 
    conn.open(); 
    using (SqlDataReader dr = cmd.ExecuteReader()) 
    { 
     while (dr.Read()) 
     { 
      //read here 
     } 
    } 
} 
+0

oui je comprends que l'utilisation se traduit simplement par un bloc try..finally et je pourrais tout aussi bien appeler la disposition moi-même. Mais je pense que c'est mieux de prendre l'habitude d'envelopper le bloc à l'intérieur de l'utiliser car je pourrais avoir tendance à oublier de mettre le morceau de code dans try..finnally. Merci pour la réponse. :) – xeshu

+0

OK :-) Je mentionnerai aussi que SqlDataReader est un nouvel objet, ou est au moins une référence à un objet renvoyé par l'appel de méthode, ce n'est pas une référence à la méthode. Juste mentionner parce que vous avez fait ce point en majuscules et ce n'est pas correct. La seule différence entre le lecteur et la connexion/commande est que vous avez initialisé la connexion/commande, mais vous n'avez pas initialisé le lecteur. À la fin vous avez toujours des références à tous les objets - que vous les ayez initialisés ou non. –

+0

Ah oui. Ma faute! :) – xeshu

2

Vous devez envelopper le lecteur de données dans une déclaration en utilisant la méthode ExecuteReader crée une nouvelle instance de lecteur de données qui doivent également être éliminés.