2009-07-28 29 views
100

Mỗi khác question here about Disposable objects, chúng ta có nên gọi Close() trước khi kết thúc khối sử dụng không?Tôi có phải đóng() một SQLConnection trước khi nó được xử lý không?

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(); 
} 

Trả lời

96

Vì bạn có một khối sử dụng, phương thức Dispose của SQLCommand sẽ được gọi và nó sẽ đóng kết nối:

// 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

_this._poolGroup = null; _ có nghĩa là kết nối không nhận được trở lại hồ bơi kết nối? vì vậy tôi sẽ có kết nối n-1? –

1

Không, lớp SqlConnection được thừa hưởng từ IDisposable, và khi kết thúc sử dụng (đối với các đối tượng kết nối) bắt gặp, nó tự động gọi Dispose trên lớp SqlConnection.

3

Không, việc sử dụng Chặn cuộc gọi Dispose() cho bạn, vì vậy không cần phải gọi Close().

+0

Xin lỗi, tôi phải nói rằng đối với hầu hết các đối tượng thực hiện IDisposable và có một phương thức Close(), gọi Close() đầu lên gọi Vứt bỏ() đằng sau hậu trường cho bạn anyway. –

+6

Đó không phải là cách khác xung quanh - 'Dispose()' gọi 'Close()', không phải ngược lại? – Town

+1

Cả hai, thường là. Vì một lý do nào đó, họ quyết định thực hiện điều đó, Close cũng sẽ gọi Dispose.Đối với một SqlConnection đây không phải là một vấn đề lớn, nhưng StreamWriters sẽ ném một ngoại lệ nếu bạn đóng và sau đó Dispose chúng. Đoán của tôi sẽ là họ sẽ không thay đổi hành vi đó đơn giản chỉ vì đó là những gì mọi người bây giờ mong đợi. –

2

Không, không cần phải đóng kết nối trước khi gọi Dispose.

Một số đối tượng, (như SQLConnections) có thể được sử dụng lại afer gọi Close, nhưng không phải sau khi gọi Dispose. Đối với các đối tượng khác gọi là Close giống như gọi Dispose. (ManualResetEvent và Streams Tôi nghĩ cư xử như thế này)

20

Tháo lắp SqlConnection từ việc sử dụng .NET Reflector :

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

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

Nó gọi Close() bên trong Dispose()

+1

@statenjason: bạn có thể vui lòng nói rằng làm thế nào để bạn tận dụng lợi thế của việc sử dụng disassemblers line .net reflector? – odiseh

+3

@odiseh chỉ cần tải xuống .NET Reflector, chạy reflector.exe và bạn có thể mở bất kỳ DLL .net nào (bao gồm thư viện chuẩn). Nó cung cấp cho bạn một cấu trúc cây tương tự như trình duyệt đối tượng của Visual Studio, tuy nhiên, bạn có thể kích chuột phải vào bất kỳ lớp hoặc phương thức nào và nhấn "tháo rời" nó sẽ trả lại nguồn cho bạn trong C# hoặc VB, tùy theo bạn đã chọn tùy chọn. – statenjason

3

Sử dụng Reflector, bạn có thể nhìn thấy thứ mà e Dispose phương thức SqlConnection thực sự gọi Close();

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

Từ khóa đang sử dụng sẽ đóng kết nối chính xác để không yêu cầu thêm lệnh Đóng.

Từ bài viết MSDN trên SQL Server Connection Pooling:

"Chúng tôi khuyên bạn luôn đóng kết nối khi bạn đang xong sử dụng nó để kết nối sẽ được trở lại hồ bơi Bạn có thể. thực hiện việc này bằng cách sử dụng các phương pháp Đóng hoặc Xử lý Đóng hoặc Vứt bỏ đối tượng kết nối hoặc bằng cách mở tất cả các kết nối bên trong tuyên bố sử dụng trong C# "

Việc thực hiện thực tế của SqlConnection.Dispose sử dụng .NET Reflector là như sau:

// 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 cho liên kết MSDN - Tôi thích phản xạ \ ILspy giống như anh chàng tiếp theo, nhưng các tài liệu là nơi tôi muốn đi để tìm câu trả lời của tôi. – mlhDev

Các vấn đề liên quan