Tôi có phải Đóng () một SQLConnection trước khi nó được xử lý không?


113

Theo câu hỏi khác của tôi ở đây về các đối tượng dùng một lần , chúng ta có nên gọi Close () trước khi kết thúc khối sử dụng 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();
}

Câu trả lời:


107

Vì bạn có một khối đang 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
Hiện điều này._poolGroup = null; nghĩa là kết nối không trở lại nhóm kết nối? vì vậy tôi sẽ có n-1 kết nối?
Royi Namir

25

Tháo gỡ SqlConnection khỏi 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 phản xạ .net dòng tháo lắp?
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ỳ tệp DLL .net nào (bao gồm cả thư viện chuẩn). Nó cung cấp cho bạn 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ể nhấp chuột phải vào bất kỳ lớp hoặc phương thức nào và nhấp vào "tháo rời", sau đó nó sẽ trả lại nguồn cho bạn trong C # hoặc VB, tùy theo bạn đã chọn trong các tùy chọn.
statenjason

20

Từ khóa using sẽ đóng kết nối một cách chính xác nên không cần phải gọi thêm Close.

Từ bài viết MSDN về Nhóm kết nối máy chủ SQL :

"Chúng tôi thực sự khuyên bạn nên luôn đóng kết nối khi bạn sử dụng xong để kết nối sẽ được trả về nhóm. Bạn có thể thực hiện việc này bằng cách sử dụng phương thức Đóng hoặc Loại 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 sử dụng câu lệnh trong C # "

Việc triển khai thực tế của SqlConnection.Dispose sử dụng .NET Reflector 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 người phản chiếu \ ILspy như anh chàng tiếp theo, nhưng tài liệu là nơi tôi muốn truy cập để tìm câu trả lời của mình.
mlhDev

5

Sử dụng Reflector , bạn có thể thấy rằng Disposephương thức SqlConnectionthự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);
}


3

Không, Dispose()dù sao cũng có lệnh chặn Đang sử dụng cho bạn nên không cần gọi Close().


Xin lỗi, tôi nên nói rằng đối với hầu hết các đối tượng triển khai IDisposable và có phương thức Close (), việc gọi Close () kết thúc bằng cách gọi Dispose () đằng sau hậu trường cho bạn.
Jason Evans

6
Đó không phải là ngược lại - Dispose()cuộc gọi Close(), không phải ngược lại?
Thị trấn

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

2

Không, không cần thiết phải Đóng kết nối trước khi gọi Hủy bỏ.

Một số đối tượng, (như SQLConnections) có thể được sử dụng lại sau khi 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 Close cũng giống như gọi Dispose. (Tôi nghĩ ManualResetEvent và Streams hoạt động như thế này)


1

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

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.