2013-08-13 30 views
8

Trong this thread, có một ý kiến ​​cho rằng sau khi phẫu thuật, trường hợp của SqlDataAdapter được xử lý một cách rõ ràng như vậy.Tôi có cần phải loại bỏ SqlDataAdapter một cách rõ ràng không?

String connString = @"your connection string here"; 
String query = "select * from table"; 

SqlConnection conn = new SqlConnection(connString);   
SqlCommand cmd = new SqlCommand(query, conn); 
conn.Open(); 
SqlDataAdapter da = new SqlDataAdapter(cmd); 
da.Fill(dataTable); 
conn.Close(); 
da.Dispose(); 

Có thực sự cần thiết không? Còn GC thì sao?

Trả lời

6

Bạn nên loại bỏ các đối tượng IDisposable một cách thủ công. Có một shortcut cú pháp tốt đẹp cho này:

using (SqlConnection con = new SqlConnection(connstring)) 
using (SqlCommand com = new SqlCommand()) 
using (SqlDataAdapter da = new SqlDataAdapter()) 
{ 
    com.Connection = con; 
    //etc.. 
} 

Bằng cách này trình biên dịch sẽ đảm bảo Vứt bỏ được kêu gọi tất cả các đối tượng được tạo trong "sử dụng" sau khi mã trong dấu ngoặc móc kết thúc việc thực hiện (nó sử dụng try..finally làm điều này).

GC không chịu trách nhiệm kêu gọi Dispose trên đối tượng của bạn, đó là trách nhiệm chính là để thu thập các đối tượng từ đống mà không còn tham chiếu.Một ngoại lệ cho điều này là nếu lớp của bạn là Finalizable. Trong trường hợp này GC sẽ đảm bảo rằng finalizer của đối tượng của bạn được gọi đầu tiên, và sau đó nó được thu thập. Bạn có thể gọi Dispose trong Finalizer của bạn và có một mô hình tốt đẹp cho điều này được gọi là "Dispose Method": http://msdn.microsoft.com/en-us/library/fs2xkftw.aspx

Nhưng quy tắc chung là (với một vài trường hợp ngoại lệ): Nếu bạn đang instantiating một đối tượng thực hiện IDisposable, đó là trách nhiệm của bạn để gọi Dispose trên đó.

5

Từ ví dụ mã đưa vào acrticle MSDN cho SqlDataAdapter Class

private static DataSet SelectRows(DataSet dataset, string connectionString,string queryString) 
{ 
    using (SqlConnection connection = 
     new SqlConnection(connectionString)) 
    { 
     SqlDataAdapter adapter = new SqlDataAdapter(); 
     adapter.SelectCommand = new SqlCommand(
      queryString, connection); 
     adapter.Fill(dataset); 
     return dataset; 
    } 
} 

Các SqlConnection được gói gọn trong một điều khoản sử dụng, nhưng không phải là SqlDataAdapter.

Vì vậy, tôi sẽ làm như vậy, không bắt buộc.

Điều đó nói rằng, một số nghiêng về phía Nếu nó triển khai IDisposable, hãy xử lý nó.

Trong trường hợp đó, bạn cũng có thể quấn SqlDataAdapter trong một using statement. Từ bài viết được liên kết đó:

Theo quy tắc, khi bạn sử dụng đối tượng IDisposable, bạn nên khai báo và khởi tạo nó trong câu lệnh sử dụng.

1
String connString = @"your connection string here"; 
String query = "select * from table"; 

SqlConnection conn = new SqlConnection(connString);   
SqlCommand cmd = new SqlCommand(query, conn); 
conn.Open(); 
**Using(SqlDataAdapter da = new SqlDataAdapter(cmd)) 
{ 
    da.Fill(dataTable); 
    conn.Close(); 
}** 

Sử dụng sẽ vứt bỏ nó khi bạn đã đến cuối khối.

+5

Và thêm 'sử dụng' cho kết nối ... Đó là tài nguyên quan trọng nhất ở đây. –

2

Theo quy tắc ... có, bạn có.
Có một số trường hợp, khi gọi tới số Dispose là không bắt buộc, nhưng những trường hợp này dựa trên chi tiết triển khai và không được coi là phương pháp chung.

Dùng một lần không phải là về việc thu gom rác thải. Đó là về xóa tài nguyên xác định. Những thứ này là những vũ trụ song song.

GC có thể thu thập đối tượng, thực hiện IDisposable mà không cần gọi tới số Dispose. Nhưng nếu đối tượng đó nắm giữ một hệ điều hành, ví dụ, bạn có hai cách: hoặc xử lý ngay lập tức (gọi Dispose), hoặc chờ finalizer (nhưng khi finalizer sẽ chạy, chỉ biết GC).

Khi tài nguyên của bạn được quản lý, mọi thứ thậm chí còn tồi tệ hơn.
Tài nguyên được quản lý không được phát hành trong finalizers. Do đó, tất cả các tài nguyên dọn dẹp là trách nhiệm của phương pháp Dispose. Nếu bạn không gọi Dispose, tài nguyên được quản lý sẽ không bao giờ được dọn sạch (mẫu phổ biến nhất là hủy đăng ký sự kiện), điều này sẽ đưa bạn đến rò rỉ bộ nhớ.

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