2009-11-27 16 views
22

Zwykle używam kodu:Czy SqlCommand.Dispose() jest wymagana, jeśli skojarzony SqlConnection zostanie usunięty?

using (var connection = new SqlConnection(ConfigurationManager.ConnectionStrings["MyConn"].ConnectionString)) 
{ 
    var command = connection.CreateCommand(); 
    command.CommandText = "..."; 
    connection.Open(); 
    command.ExecuteNonQuery(); 
} 

moja command automatycznie usuwane? Czy nie i muszę go opakować w blok using? Czy wymagane jest dysponowanie SqlCommand?

+0

To źle, Microsoft uczynił SqlCommand komponentem. Jeśli naprawdę potrzebowali komponentu do obsługi projektanta, mógł to być wrapper na lekkim SqlCommand, który nie implementuje IDisposable. –

Odpowiedz

22

Wystarczy to zrobić:

using(var connection = new SqlConnection(ConfigurationManager.ConnectionStrings["MyConn"].ConnectionString)) 
using(var command = connection.CreateCommand()) 
{ 
    command.CommandText = "..."; 
    connection.Open(); 
    command.ExecuteNonQuery(); 
} 

niestawienie zbyć na komendzie niczego zbyt złego nie zrobi. Jednak wywołanie na nim się wyłączy supress the call to the finalizer, dzięki czemu wywołanie może spowodować zwiększenie wydajności.

+11

"Nie dzwoniąc do komendy nie zrobi nic złego." To prawda, ale nie przyzwyczaj się do tego; Dotyczy to tylko 'SqlCommand's. Z drugiej strony, nie wyrzucanie 'SqlCeCommand' na przykład * spowoduje * szybkie wyczerpanie pamięci urządzenia mobilnego. (Właśnie tam byłem, robiłem to ...) – Heinzi

+2

'Dispose' nie tłumi finalizacji, ponieważ robi to konstruktor. –

8

Najbezpieczniejszą zasadą jest zawsze wywoływanie Dispose() na obiekcie, jeśli implementuje on IDisposable, jawnie lub za pomocą bloku użytego. Mogą występować przypadki, w których nie jest to wymagane, ale wywoływanie tego tak czy inaczej nigdy nie powinno powodować problemów (jeśli klasa jest poprawnie napisana). Nigdy nie wiesz, kiedy implementacja może się zmienić, co oznacza, że ​​tam, gdzie wcześniej nie było to wymagane, jest to zdecydowanie wymagane.

W podanym przykładzie można dodać dodatkowy wewnętrzny blok poleceń dla polecenia, a także zachować zewnętrzny blok obsługi połączenia.

+2

Tak, najbezpieczniejszą zasadą jest zawsze wyrzucać przedmioty jednorazowego użytku - zwłaszcza jeśli * stworzyłeś * to! Na przykład nie jest dobrym pomysłem napisanie metody akceptującej strumień i pozbycie się strumienia wewnątrz tej metody. Kolejnym zastrzeżeniem jest to, że nie można zawsze bezkarnie posługiwać się oświadczeniem o używaniu. Usługi proxy WCF są jedynym praktycznym przykładem, jaki znam. Jeśli coś pójdzie nie tak po stronie zdalnej i otrzymasz wyjątek, kanał zamknie się, a Wyrzuć, a następnie wyrzuci nowy wyjątek, zastępując pierwotny wyjątek, co może być poważnym problemem. –

+1

kolejny powód, by nie używać WCF! dzięki za napiwek ;-) –

1

Możesz dowiedzieć się tego rodzaju rzeczy za pomocą Reflector.

Miałem małą wykopalnię (sugerowałbym, żebyś się zagłębił, aby być całkowicie pewnym reszty, chociaż nie starałem się tak mocno) i wygląda na to, że gdy zabijasz połączenie, nie ma żadnej możliwości wszystkich dzieci związanych z tym połączeniem. Co więcej, faktycznie nie wygląda na to, że zbieranie poleceń faktycznie tak wiele robi. Ustawi pole na wartość null, oddzieli się od kontenera (może to zapobiec wyciekowi zarządzanej pamięci) i podniesie zdarzenie (może to być ważne, ale nie widzę, kto nasłuchuje tego zdarzenia).

Tak czy inaczej, dobrą praktyką jest używanie tych rzeczy w używanym bloku lub aby się go pozbyć za pomocą wzoru utylizacji w obiekcie, który utrzymuje połączenie (jeśli zamierzasz przytrzymać to polecenie przez jakiś czas).

4

Tak, powinieneś, nawet jeśli implementacja obecnie nie robi wiele, nie wiesz, jak to się zmieni w przyszłości (na przykład nowsze wersje). Ogólnie rzecz biorąc, należy pozbyć się wszystkich obiektów, które implementują IDisposable po bezpiecznej stronie.

Jednakże, jeśli operacja jest odroczone, a nie kontrolować pełny zakres (na przykład podczas pracy asynchroneously lub gdy zwrócenie SqlDataReader lub tak), można ustawić CommandBehavior do CloseConnection tak, że jak tylko czytelnika jest zrobione, połączenie jest właściwie zamknięte/utylizowane.

2

W praktyce można pominąć Dispose. Nie zwalnia żadnych zasobów. Nie blokuje nawet finalizacji, ponieważ konstruktor to robi.

Teoretycznie Microsoft może zmienić implementację, aby zdobyć niezarządzany zasób, ale mam nadzieję, że wyjdzie z interfejsem API, który pozbyłby się klasy bazowej Component na długo przed tym, zanim to zrobi.

Powiązane problemy