2010-08-02 7 views
11

Wiem, że wcześniej zadałem pokrewne pytanie. Właśnie miałem inną myśl.przy użyciu 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 
      } 
     } 
    } 
} 

Argumentem jest to, że: Ponieważ obiekt SqlDataReaderdr Nie jest to nowy obiekt np połączenia lub polecenia obiektów, jego po prostu odniesienie wskazując metody cmd.ExecuteReader(), muszę umieścić czytnik wewnątrz using. (Teraz na podstawie mojego poprzedniego posta, rozumiem, że każdy obiekt, który używa IDisposable musi być umieszczony w using, a SQLDataReader dziedziczy po IDisposable, więc muszę go umieścić. Czy mam rację w moim osądzie?) Jestem po prostu zdezorientowany, ponieważ nie jest to nowy obiekt, czy spowodowałby jakiekolwiek problemy z wyrzuceniem obiektu, który jest po prostu wskaźnikiem odniesienia do polecenia?

Dziękujemy

+0

"cmd.ExecuteReader" jest rodzajem metody odniesienia. "cmd.ExecuteReader()" (nawias zawiadomień) to wywołanie metody. –

Odpowiedz

26

Myślę, że się mylisz. dr jest odniesieniem do obiektu zwróconego przez cmd.ExecuteReader, który będzie nowym obiektem. W twoim przykładzie nic się nie pozbędzie, więc tak musi być w using lub ręcznie usuwane.

Twoja opinia o IDisposable implementatorach potrzebujących być w using jest niepoprawna. Będą działać dobrze na zewnątrz. Instrukcja using jest po prostu syntaktycznym cukrem dla try ... finally. Rzeczy wymagające implementacji IDisposable powinny być wywoływane, ponieważ sygnalizują, że muszą dysponować określonym stanem w deterministyczny sposób.

Pamiętaj, że jeśli nie zadzwonisz pod numer Dispose, nie zawsze jest to problem. Niektóre obiekty implementują także finalizator, który zostanie wywołany przez garbage collector. Jeśli nie implementują finalizatora, mogą pozostawić nieobsługiwaną pamięć nieodzyskaną. Pozostanie to nieodebrane do czasu zamknięcia aplikacji. Cała zarządzana pamięć jest w końcu odzyskiwana, chyba że nie można jej pominąć w przypadku zbierania śmieci.

Re napisane:

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

tak, rozumiem, że użycie po prostu tłumaczy się w try..finally block i mogę równie dobrze nazwać dispose my self. Ale myślę, że lepiej jest zrobić nawyk owijania bloku wewnątrz używania, ponieważ mógłbym zapomnieć o umieszczeniu kawałka kodu w try..finnally. Dziękuję za odpowiedź. :) – xeshu

+0

To jest w porządku :-) Wspomnę też, że SqlDataReader jest nowym obiektem lub przynajmniej jest odniesieniem do obiektu zwróconego przez wywołanie metody, nie jest to odwołanie do metody. Po prostu wspomniałem, ponieważ pisałeś wielkimi literami i nie było to poprawne. Jedyną różnicą między czytnikiem a połączeniem/poleceniem jest zainicjowanie połączenia/polecenia, ale nie zainicjowano czytnika. Na końcu nadal masz odniesienia do wszystkich obiektów - niezależnie od tego, czy zainicjowałeś je, czy nie. –

+0

Ah tak. Mój błąd! :) – xeshu

2

Należy owinąć czytnik danych w użyciu instrukcji jako metoda ExecuteReader tworzy nową instancję czytnika danych, które powinny być unieszkodliwiane.