2011-10-27 28 views
5

Tôi đã được khuyên nên đặt toàn bộ khối using bên trong một try, nếu không phạm vi using sẽ ngăn chặn ngoại lệ bị bắt. Tuy nhiên, điều đó sẽ không ngăn không cho using xử lý đúng tài nguyên của nó nếu một ngoại lệ bị ném ra? Nếu tôi có mã bên dưới, tôi nên đặt các khối try ở đâu?Nơi đặt thử/nắm bắt khi sử dụng IDisposable

using (connSQL = new SqlConnection(strConn)) 
{ 
    connSQL.Open(); 
    using (SqlCommand commSQL = new SqlCommand(strPreparedStatement, connSQL)) 
    { 
     if (sqlParameters != null) 
     { 
      for (int i = sqlParameters.GetLowerBound(0); i <= sqlParameters.GetUpperBound(0); i++) 
      { 
       commSQL.Parameters.Add(sqlParameters[i]); 
      } 
     } 
     drSQL = commSQL.ExecuteReader(); 
     dtReturn.Load(drSQL); 

     commSQL.Parameters.Clear(); 
    } 
} 

Trong ứng dụng này, việc đảm bảo kết nối với cơ sở dữ liệu không quan trọng hơn nhiều là không bắt đầu tích lũy do ngoại lệ.

Trả lời

9

Tuyên bố using sẽ đã ngăn chặn các kết nối từ tích lũy - nó phía dọn dẹp những thứ cho bạn , bằng cách thực sự là một khối try/finally với một cuộc gọi đến Dispose trong khối finally. Nếu bạn cũng muốn một khối try/catch, bạn có thể đặt nó bên trong hoặc bên ngoài - nhưng bạn có chắc chắn không nên ở cấp cao hơn không? Bạn thực sự mong đợi như thế nào để xử lý ngoại lệ?

Là một sang một bên, nó không phải là rõ ràng lý do tại sao bạn xóa các thông số từ lệnh khi lệnh sắp được xử lý anyway ...

Tôi sẽ khuyến khích bạn khai báo các biến trong using báo cáo quá , để bạn không phải cố gắng đọc từ họ bên ngoài khối:

using (SqlConnection connSQL = new SqlConnection(strConn)) { 

Nói chung, thích cung cấp cho các biến của bạn phạm vi hẹp nhất có thể. Ồ, và số SqlDataReader của bạn cũng phải có trong tuyên bố using. Nó có thể không quan trọng như bạn đang đóng kết nối và lệnh anyway, nhưng tôi sẽ làm điều đó như là một điểm của nguyên tắc - nó thực hiện IDisposable, vì vậy bạn nên xử lý nó.

Ồ, và cách bạn lặp lại trên sqlParameters là khá dài lúc này. foreach làm cho nó đơn giản hơn, và thậm chí nếu nó không tôi muốn sử dụng for (int i = 0; i < sqlParameters.Length; i++) trừ khi tôi có lý do để tin rằng nó không phải là một mảng "đơn giản".

Vì vậy, mã tương đương của tôi sẽ giống như thế này:

using (SqlConnection connection = new SqlConnection(connectionString)) 
{ 
    connection.Open(); 
    using (SqlCommand command = new SqlCommand(strPreparedStatement, connection)) 
    { 
     if (sqlParameters != null) 
     { 
      // If sqlParameter is an array, you can just use 
      // command.Parameters.AddRange(sqlParameters) instead 
      foreach (SqlParameter parameter in sqlParameters) 
      { 
       command.Parameters.Add(parameter); 
      } 
     } 
     using (SqlDataReader reader = command.ExecuteReader()) 
     { 
      DataTable table = new DataTable(); 
      // Perform any extra initialization here 
      table.Load(reader); 
      return table; 
     } 
    } 
} 
+0

Thú vị. Tất cả các điểm rất tốt. Tôi đánh giá cao điểm về 'SqlDataReader'. Tôi hoàn toàn bỏ lỡ điều đó. – Andrew

+0

Thấy chỉnh sửa của bạn, lại đơn giản hơn nhiều. Cảm ơn bạn. – Andrew

1

Không cần phải đặt trycatchusing thực hiện nó ngầm, trên thực tế nó sử dụng thử cuối cùng và chắc chắn nó sẽ phân phối các đối tượng.

Đây là MSDN using Sample về cố gắng nắm bắt và sử dụng:

{ 
    Font font1 = new Font("Arial", 10.0f); 
    try 
    { 
    byte charset = font1.GdiCharSet; 
    } 
    finally 
    { 
    if (font1 != null) 
     ((IDisposable)font1).Dispose(); 
    } 
} 

bằng:

using (Font font3 = new Font("Arial", 10.0f), 
      font4 = new Font("Arial", 10.0f)) 
{ 
    // Use font3 and font4. 
} 
+0

Nitpick - 'sử dụng' thực hiện thử/cuối cùng, không thử/bắt – Greg

+0

Sai, nó sẽ không thực hiện bắt. Nhưng chỉ cố gắng và cuối cùng! – Zenwalker

+0

@zenwalker Tôi đã viết nó thực hiện nó ngầm (tôi có nghĩa là những gì OP muốn từ thử bắt) cũng tôi nói rằng sử dụng làm điều đó với cố gắng cuối cùng. –

2

Bạn cần phải quấn đọc dữ liệu trong một tuyên bố sử dụng cũng vì nó là một nguồn tài nguyên dùng một lần:

using (var connSQL = new SqlConnection(strConn)) 
using (var commSQL = connSQL.CreateCommand()) 
{ 
    connSQL.Open(); 
    commSQL.CommandText = strPreparedStatement; 
    if (sqlParameters != null) 
    { 
     for (int i = sqlParameters.GetLowerBound(0); i <= sqlParameters.GetUpperBound(0); i++) 
     { 
      commSQL.Parameters.Add(sqlParameters[i]); 
     } 
    } 
    using (var drSQL = commSQL.ExecuteReader()) 
    { 
     dtReturn.Load(drSQL); 
    } 
} 

tôi cũng đã thực hiện các kết nối, lệnh và các đối tượng đọc dữ liệu cục bộ được xác định trong phạm vi khối này.

Theo như tuyên bố try/finally, bạn không còn cần nó vì câu lệnh using đảm bảo rằng phương thức Vứt bỏ sẽ được gọi ngay cả trong trường hợp ngoại lệ. Và phương pháp này cho các kết nối và lệnh sql đảm bảo phát hành chúng đúng cách.

+0

Điểm tốt. Tôi đã bỏ lỡ điều đó cho đến khi câu trả lời ở đây chỉ ra điều đó. Tôi cũng thích sử dụng các khối 'using' kết hợp. Tôi không chắc tại sao tôi không nghĩ mình có thể sử dụng nó ở đây. – Andrew

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