2009-02-05 36 views
24

Với mã này:Làm thế nào để bạn bắt ngoại lệ với "sử dụng" trong C#

using (var conn = new SqlConnection("...")) 
{ 
    conn.Open(); 
    using (var cmd = conn.CreateCommand()) 
    { 
     cmd.CommandText = "..."; 
     using (var reader = cmd.ExecuteReader()) 
     { 
      while (reader.Read()) 
      { 
       // ... 
      } 
     } 
    } 
} 

Tôi đang sử dụng để viết try/catch/finally khối để truy cập dữ liệu của tôi, tuy nhiên, tôi được tiếp xúc với "sử dụng" có vẻ như là một phương pháp đơn giản hơn nhiều để thực hiện việc này. Tuy nhiên, tôi đang cố gắng tìm ra cách bắt các ngoại lệ có thể xảy ra.

Bạn có thể cho tôi ví dụ về cách bạn có ngoại lệ không?

Edited thêm:

tôi đang bị dẫn dắt để tin rằng "sử dụng" là một sự thay thế cho try/catch/finally khối của tôi. Tôi hiểu rằng việc sử dụng không bắt được ngoại lệ. Vậy đây là một sự thay thế như thế nào?

+2

Đó là không phải là một sự thay thế. –

Trả lời

47

using không được thiết kế để bắt ngoại lệ; nó được thiết kế để cung cấp cho bạn một cách dễ dàng để quấn try/finally xung quanh một đối tượng cần được xử lý. Nếu bạn cần nắm bắt và xử lý các trường hợp ngoại lệ thì bạn sẽ cần phải mở rộng nó thành một số try/catch/finally hoặc đặt một số có chứa try/catch xung quanh toàn bộ sự việc.


Để trả lời chỉnh sửa của bạn (là using một sự thay thế cho try/catch/finally?) Thì không có, nó không phải là. Hầu hết thời gian khi sử dụng một nguồn tài nguyên dùng một lần bạn sẽ không xử lý ngoại lệ ở đó và sau đó vì thường không có gì hữu ích mà bạn có thể làm. Vì vậy, nó cung cấp một cách thuận tiện để đảm bảo rằng tài nguyên được làm sạch không phụ thuộc vào những gì bạn đang cố gắng để làm việc hay không. Mã số thường giao dịch với tài nguyên dùng một lần đang hoạt động ở mức quá thấp để quyết định hành động chính xác nào là thất bại, do đó, ngoại lệ còn lại để truyền cho người gọi có thể quyết định hành động nào (ví dụ: thử lại, không thành công , nhật ký, v.v.). Nơi duy nhất bạn muốn sử dụng khối catch với tài nguyên dùng một lần là bạn sẽ dịch ngoại lệ (tức là, tôi giả định, lớp truy cập dữ liệu của bạn đang làm gì).

6

Sử dụng câu lệnh không liên quan gì đến Ngoại lệ. Sử dụng khối chỉ đảm bảo rằng Vứt bỏ được gọi trên đối tượng trong khối sử dụng, khi nó thoát khỏi khối đó. I.E:

using(SqlConnection conn = new SqlConnection(conStr)) 
{ 
    //use conn 
}//Dispose is called here on conn. 

Nếu mở kết nối ngoại lệ (hoặc bất kỳ thứ gì khác trong khối đó) nó sẽ vẫn bong bóng lên trên và sẽ giống như bất kỳ ngoại lệ nào khác.

7

Nếu bạn muốn bắt ngoại lệ, có thể bạn nên quay lại sử dụng try/catch/finally. Chỉ cần đặt các cuộc gọi .Dispose() trong khối cuối cùng.

+1

Anh ta có thể bọc việc sử dụng vào một khối try/catch. Nếu một lỗi bị bắt, Vứt bỏ sẽ được gọi (nếu nó tồn tại) trước khi vào bẫy. – Leonidas

+2

Đó là sự thật, nhưng sau đó bạn có thêm một mức thụt đầu dòng và câu lệnh sử dụng không còn thuận tiện nữa. Tôi muốn chỉ có một thử/bắt/cuối cùng xử lý tất cả mọi thứ (nhưng đó là một điều phong cách nhỏ). –

+1

Nhưng ngay cả với xử lý lỗi đơn giản, nó có thể dễ dàng để viết mã trông giống như nó gọi là 'Dispose()' nhưng không thành công trong một số trường hợp. 'using()' ít nhất đảm bảo nó được làm sạch chính xác, ngay cả khi nó làm cho việc xử lý ngoại lệ chi tiết gần như không thể. – binki

8

Quấn tất cả các câu lệnh sử dụng vào thử/nắm bắt. Giống như mọi người khác đã nói, sử dụng là để dọn dẹp các lớp triển khai giao diện IDisposable

try 
{ 

using (var conn = new SqlConnection("...")) 
{ 
    conn.Open(); 
    using (var cmd = conn.CreateCommand()) 
    { 
     cmd.CommandText = "..."; 
     using (var reader = cmd.ExecuteReader()) 
     { 
      while (reader.Read()) 
      { 
       // ... 
      } 
     } 
    } 
} 
} 
catch(Exception ex) 
{ 
//Handle, log, rethrow exception 
} 
+0

Làm thế nào là điều này tốt hơn mà cố gắng/bắt/cuối cùng và kêu gọi vứt bỏ trong khối cuối cùng của tôi? – GregD

+0

Erik, tại sao bạn lại gọi vứt bỏ trong khối cuối cùng? Khi nào bạn có thể sử dụng các câu lệnh sử dụng? Nếu bạn sử dụng khối cuối cùng sau đó bạn phải khai báo các đối tượng bên ngoài khối thử ... –

+0

Nội bộ đó là cùng một IL tuyên bố sử dụng sẽ tạo ra Charles. Nó thực sự chỉ là kẹo cú pháp. –

3

Bạn vẫn có thể bắt (hoặc bỏ qua) ngoại lệ chính xác như bạn đã làm trước đây. Vấn đề là bạn không cần phải lo lắng về việc xử lý kết nối cơ sở dữ liệu nữa.

tức, Nếu ứng dụng của bạn đòi hỏi bạn phải bẫy ngoại lệ đối với một số lý do nào khác (ví dụ, khai thác gỗ) sau đó đi về phía trước, nhưng bạn không còn cần phải làm như vậy nếu bạn chỉ muốn vứt bỏ các kết nối cơ sở dữ liệu:

using (SqlConnection conn = new SqlConnection(...)) 
{ 
    // do your db work here 
    // whatever happens the connection will be safely disposed 
} 

Nếu bạn muốn nắm bắt những ngoại lệ đối với một số lý do khác, bạn vẫn có thể làm như vậy:

try 
{ 
    using (SqlConnection conn = new SqlConnection(...)) 
    { 
     // do your db work here 
     // whatever happens the connection will be safely disposed 
    } 
} 
catch (Exception ex) 
{ 
    // do your stuff here (eg, logging) 
    // nb: the connection will already have been disposed at this point 
} 
finally 
{ 
    // if you need it 
} 
+0

Thật buồn cười. Tôi đã tự hỏi nếu bạn sẽ bật đầu của bạn ở đây :) – GregD

10
using (var cmd = new SqlCommand("SELECT * FROM Customers")) 
{ 
    cmd.CommandTimeout = 60000; 
    ... 
} 

là cú pháp đường cho

var cmd = new SqlCommand("SELECT * FROM Customers"); 
try 
{ 
    cmd.CommandTimeout = 60000; 
    ... 
} 
finally 
{ 
    if (cmd != null) 
     cmd.Dispose(); 
} 

Vì vậy, khi mọi người đang nói với bạn rằng "sử dụng" là một sự thay thế cho try/catch/finally họ đang ngụ ý rằng bạn nên sử dụng dạng dài tay nhưng thêm vào trong khối catch của bạn:

var cmd = new SqlCommand("SELECT * FROM Customers"); 
try 
{ 
    cmd.CommandTimeout = 60000; 
    ... 
} 
catch (Exception ex) 
{ 
    ...//your stuff here 
} 
finally 
{ 
    if (cmd != null) 
     cmd.Dispose(); 
} 
+0

Nếu cmd được tạo ra trong khối thử, bạn không thể gọi vứt bỏ nó trong khối cuối cùng. – Kredns

+1

@Lucas Aardvark - tất nhiên, cảm ơn! Đã sửa. – RogueBadger

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