2009-07-28 10 views
100

Do mojego innego question here about Disposable objects, czy powinniśmy wywołać Close() przed zakończeniem używania bloku?Czy muszę zamknąć() połączenie SQLC, zanim zostanie usunięte?

using (SqlConnection connection = new SqlConnection()) 
using (SqlCommand command = new SqlCommand()) 
{ 
    command.CommandText = "INSERT INTO YourMom (Amount) VALUES (1)"; 
    command.CommandType = System.Data.CommandType.Text; 

    connection.Open(); 
    command.ExecuteNonQuery(); 

    // Is this call necessary? 
    connection.Close(); 
} 

Odpowiedz

96

Skoro masz stosując blok, sposób utylizować SQLCommand będzie nazwane i będzie zamknąć połączenie:

// System.Data.SqlClient.SqlConnection.Dispose disassemble 
protected override void Dispose(bool disposing) 
{ 
    if (disposing) 
    { 
     this._userConnectionOptions = null; 
     this._poolGroup = null; 
     this.Close(); 
    } 
    this.DisposeMe(disposing); 
    base.Dispose(disposing); 
} 
+1

Czy _this._poolGroup = null; _ oznacza, że ​​połączenie nie wraca do puli połączeń? więc będę miał połączenia n-1? –

1

Nie, klasa SqlConnection dziedziczy z IDisposable, a kiedy koniec użyciu (dla obiektu połączenia) spotyka, automatycznie wywołuje Dispose na klasy SqlConnection.

3

Nie, po tym, jak korzystasz z bloku blokującego Dispose(), więc nie trzeba dzwonić pod numer Close().

+0

Przepraszam, powinienem powiedzieć, że dla większości obiektów, które implementują IDisposable i mają metodę Close(), wywołanie close() końce nawet dzwonić do Dispose() za kulisami. –

+6

Czy nie jest odwrotnie - 'Dispose()' wywołania 'Close()', a nie odwrotnie? – Town

+1

To zwykle jedno i drugie. Z jakiegoś powodu zdecydowali się na wdrożenie tego, co Close nazwałoby również Dispose.Dla SqlConnection nie jest to wielka sprawa, ale StreamWriters rzuci wyjątek, jeśli zamkniesz, a następnie Wyrzucisz. Sądzę, że nie zmienią tego zachowania, ponieważ właśnie tego oczekują ludzie. –

2

Nie, nie jest konieczne Zamknięcie połączenia przed wywołaniem Pozbyć się.

Niektóre obiekty (takie jak SQLConnections) mogą być ponownie użyte afer calling Close, ale nie po wywołaniu Dispose. Dla innych obiektów wywołanie Close jest takie samo, jak wywołanie Dispose. (ManualResetEvent i Strumienie myślę zachowują się jak ten)

20

Demontaż SqlConnection z użyciem .NET Reflector :

protected override void Dispose(bool disposing) 
{ 
    if (disposing) 
    { 
     this._userConnectionOptions = null; 
     this._poolGroup = null; 
     this.Close(); 
    } 

    this.DisposeMe(disposing); 
    base.Dispose(disposing); 
} 

wzywa Close() wewnątrz Dispose()

+1

@statenjason: czy mógłbyś powiedzieć, w jaki sposób wykorzystujesz wykorzystanie dezasemblera linii .net reflector? – odiseh

+3

@odiseh wystarczy pobrać .NET Reflector, uruchomić program reflector.exe i otworzyć dowolną bibliotekę .net (w tym bibliotekę standardową). Zapewnia strukturę drzewa podobną do przeglądarki obiektów Visual Studio, jednak można kliknąć prawym przyciskiem myszy dowolną klasę lub metodę i kliknąć "disasemblować", a następnie zwróci źródło do ciebie w C# lub VB, w zależności od tego, co wybierzesz w opcje. – statenjason

3

Korzystanie Reflector, można zobaczyć, że th e Dispose metoda z SqlConnection faktycznie nazywa się Close();

protected override void Dispose(bool disposing) 
{ 
    if (disposing) 
    { 
     this._userConnectionOptions = null; 
     this._poolGroup = null; 
     this.Close(); 
    } 
    this.DisposeMe(disposing); 
    base.Dispose(disposing); 
} 
15

Słowo kluczowe przy użyciu spowoduje prawidłowe zamknięcie połączenia, więc dodatkowe wywołanie funkcji Zamknij nie jest wymagane.

Z artykułu MSDN na SQL Server Connection Pooling:

„Zalecamy zawsze zamknąć połączenia, gdy jesteś zakończeniu pracy tak, że połączenie będą zwracane do puli Można. to zrobić stosując albo Zamknij lub zbywać metody obiektu połączenia lub otwierając wszystkie połączenia wewnątrz z wykorzystaniem rachunku w C#”

Faktyczna realizacja SqlConnection.Dispose użyciu .NET Reflector jest następujący:

// System.Data.SqlClient.SqlConnection.Dispose disassemble 
protected override void Dispose(bool disposing) 
{ 
    if (disposing) 
    { 
     this._userConnectionOptions = null; 
     this._poolGroup = null; 
     this.Close(); 
    } 
    this.DisposeMe(disposing); 
    base.Dispose(disposing); 
} 
+1

+1 dla łącza MSDN - Lubię reflektor \ ILspy jak następny facet, ale dokumenty są gdzie chciałbym znaleźć odpowiedzi. – mlhDev