2012-04-30 27 views
7

tôi tìm thấy mã này trên trang web MSDN đây http://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqlconnection.open.aspx:SqlConnection trong C# - thực hành lập trình an toàn

private static void OpenSqlConnection(string connectionString) 
{ 
    using (SqlConnection connection = new SqlConnection(connectionString)) 
    { 
     connection.Open(); 
     Console.WriteLine("ServerVersion: {0}", connection.ServerVersion); 
     Console.WriteLine("State: {0}", connection.State); 
    } 
} 

Câu hỏi của tôi là ... trang web cũng lưu ý rằng .Open() có thể ném InvalidOperationExceptions và SqlExceptions, nhưng ví dụ này doesn Không giống như nó xử lý chúng.

Đây có phải chỉ vì chúng đang ngắn gọn với mã hoặc có lý do khiến chúng không đáng xử lý ở đây không? là họ có thể handld bằng cách sử dụng xây dựng trong một số cách?

+0

'.Open()' sẽ ném một ngoại lệ nếu connectionString không hợp lệ, đối tượng 'SqlConnection' là rỗng hoặc trống hoặc nếu không có kết nối nào có thể được thực hiện với máy chủ (hoặc cơ sở dữ liệu cục bộ). Trong trường hợp đó, họ giả định rằng chuỗi kết nối là hợp lệ và câu lệnh using đảm bảo rằng kết nối không phải là null. – DangerMonkey

Trả lời

9

Đây có phải chỉ vì chúng ngắn gọn với mã hay không, hoặc có lý do khiến chúng không đáng xử lý ở đây không? chúng có thể được handld bởi cấu trúc sử dụng theo một cách nào đó không?

Từ khóa using là cú pháp đường cho try/finally và mặc dù trường hợp ngoại lệ có thể sẽ không được xử lý trên mã bạn tham chiếu, Connection SQL sẽ được xử lý đúng cách. Họ có lẽ không xử lý các trường hợp ngoại lệ có thể một cách rõ ràng bởi vì nhiều người thích để cho các bong bóng ngoại lệ lên đến lớp cao nhất và xử lý các trường hợp ngoại lệ ở đó.

+0

Cảm ơn tất cả mọi người, điều đó làm cho nó trở nên rất nhiều. Tôi đang đến từ một backgorund C++, vì vậy tôi muốn kiểm tra lại một số trong những điều này để đảm bảo rằng họ không làm nhiều hơn tôi nghĩ rằng họ là :) –

3

Nó phụ thuộc nếu có bất cứ điều gì bạn có thể "làm" khi đặt những ngoại lệ này.

Nếu không - thường được coi là phương pháp hay nhất để cho phép ngoại lệ bong bóng lên chồng, cho đến khi chúng đạt đến điểm chúng có thể được xử lý một cách có ý nghĩa (có thể chỉ ghi nhật ký lỗi 500, trong trường hợp web -app)

4

Ví dụ MSDN được viết để cung cấp một ví dụ dễ đọc, không phải để dạy các phương pháp hay nhất. Đó là một lý do tại sao mọi người không nên sao chép/dán mã mà không hiểu nó.

mỗi MSDN

Báo cáo sử dụng gọi phương thức Dispose trên các đối tượng trong cách chính xác , và (khi bạn sử dụng nó như thể hiện trước đó) nó cũng làm cho đối tượng bản thân để đi ra khỏi phạm vi ngay khi Dispose được gọi.

Nó sẽ đóng kết nối mở (thông qua việc sử dụng cuối cùng). Nó sẽ không bắt được ngoại lệ bị ném. Nó làm như vậy bằng cách gói câu lệnh đính kèm trong một thử/cuối cùng. Không có bắt.

+0

Đồng ý. Một phần của vấn đề với thực hành tốt nhất trong mã ví dụ là nó khó khăn hơn nhiều cho người mới để tìm ra những gì đang xảy ra. – NotMe

2

Các trường hợp này đang được xử lý.

Tuyên bố using được dịch sang mẫu vứt bỏ thích hợp cũng xử lý việc xử lý trong trường hợp ngoại lệ.

Trong trường hợp này, ngay cả khi ngoại lệ được ném, kết nối sẽ được xử lý.

Ngoại lệ sẽ tự động phát sinh.

Xem using Statement trên MSDN để biết chi tiết.

+0

bạn có thể giải thích điều này nhiều hơn một chút cho tôi hoặc cho một liên kết tôi có thể đọc không? –

+1

Chúng không bị xử lý *. –

+1

@KendallFrey - Các trường hợp xử lý sẽ được xử lý bất kể ngoại lệ. Câu trả lời được lặp lại. – Oded

0

Tuyên bố sử dụng đảm bảo rằng Vứt bỏ được gọi ngay cả khi một ngoại lệ xảy ra trong khi bạn đang gọi các phương thức trên đối tượng.Try/catch là tốn kém.try/catch có thể ảnh hưởng đến tối ưu hóa trình biên dịch và những gì lập trình viên sẽ sử dụng try/catch trên làm một cái gì đó đơn giản như kiểm tra cho null. Nó chỉ là thực hành xấu. Bắt một ngoại lệ sẽ luôn chậm hơn so với thực hiện kiểm tra đơn giản. Tôi không nói sử dụng chúng nhưng không sử dụng chúng thay cho lập trình phòng thủ.

Ngoài ra, nhìn vào mã "mở" lệnh sẽ được gọi là chỉ khi có một giá trị connection..so không phải lo lắng ....

"Sử dụng" là giống như đặt các đối tượng bên trong một thử chặn và sau đó gọi Dispose trong một khối cuối cùng.

Nếu bạn vẫn cần phải xử lý bất kỳ trường hợp ngoại lệ đặc biệt, bao gồm try..catch ..

+0

-1: 'using' không có gì để ngăn chặn các ứng dụng từ bị rơi. –

+0

Cảm ơn John đã làm rõ điều đó .... – Charls

0

Mẫu này là khó hiểu, trong khi về mặt kỹ thuật chính xác. Trong một ứng dụng thế giới thực, mẫu này "như là" không có giá trị.
Chúng thậm chí không trả lại SqlConnection thành mã gọi.
Vì vậy, "chúng đã ngắn gọn với mã" như bạn đã nói.

Trong một kịch bản thế giới thực, bạn có thể có một phương pháp như thế này

private static SqlConnection OpenSqlConnection(string connectionString) 
{ 
    SqlConnection connection = new SqlConnection(connectionString) 
    connection.Open(); 
    return connection;  
} 

và sau đó sử dụng nó trong mã của bạn (mặc dù không có nhiều để đạt được)

using(SqlConnection cnn = OpenSqlConnection(connectionString)) 
{ 
    // Do your work here 
    .... 
} 

tất nhiên bằng cách sử dụng tuyên bố ẩn tất cả các công trình để bắt ngoại lệ và đóng/xử lý tất cả mọi thứ như vậy, trong khi, về mặt kỹ thuật nói các trường hợp ngoại lệ được xử lý, trên thực tế bạn không nhận được bất kỳ manh mối nào nếu một điều gì đó không thành công.

+0

Ý của bạn là gì, "bạn không nhận được bất kỳ manh mối nào"? Bạn nhận được một ngoại lệ, đó là một "đầu mối" rất lớn. –

+0

@JohnSaunders Tôi đã nghĩ về điều này. Nếu 'using' giống như một khối try/finally, điều gì sẽ xảy ra nếu bên trong khối sử dụng chúng ta có ngoại lệ?Nó sẽ bong bóng lên bên ngoài khối và chúng ta có thể chú ý hoặc nó sẽ được 'ăn' bởi cuối cùng đeo mặt nạ bởi cú đúp đóng? – Steve

+0

Chỉ tìm thấy [this] (http://stackoverflow.com/questions/911626/catch-exceptions-within-a-using-block-vs-outside-the-using-block-which-is-bett), đọc ngay bây giờ để hiểu rõ hơn – Steve

1
using (SqlConnection connection = new SqlConnection(connectionString)) 
    { 

    } 

tương đương với

try 
{ 

    SqlConnection connection = new SqlConnection(connectionString) 
} 
finally 
{ 
    connection.Dispose(); 
} 

"sử dụng" chỉ là để đảm bảo rằng các phương pháp xử lý() trên đối tượng được gọi là (trong trường hợp này để đảm bảo kết nối được trở về kết nối hồ bơi). "sử dụng" không bao giờ có nghĩa là để thay thế bắt.

Trên các dự án tôi đã làm việc, thường chúng tôi có rất nhiều cố gắng cuối cùng. Catch chỉ được sử dụng ở mức cao nhất để ghi lại nó. Một lý do bắt không nên được sử dụng để lại ném lỗi (như trái ngược với đăng nhập nó) là bắt là rất tài nguyên chuyên sâu.