2009-10-12 28 views
5

Với phương pháp này:Tại sao SqlConnection không được xử lý/đóng?

internal static DataSet SelectDataSet(String commandText, DataBaseEnum dataBase) 
{ 
    var dataset = new DataSet(); 

    SqlConnection sqlc = dataBase == DataBaseEnum.ZipCodeDb 
          ? new SqlConnection(ConfigurationManager.AppSettings["ZipcodeDB"]) 
          : new SqlConnection(ConfigurationManager.AppSettings["WeatherDB"]); 
    SqlCommand sqlcmd = sqlc.CreateCommand(); 
    sqlcmd.CommandText = commandText; 
    var adapter = new SqlDataAdapter(sqlcmd.CommandText, sqlc); 
    adapter.Fill(dataset); 


    return dataset; 
} 

Tại sao sqlc (SqlConnection) không xử lý/đóng sau khi phương pháp gọi điện thoại đi ra khỏi phạm vi hoặc sqlc không có nhiều tài liệu tham khảo?

EDIT 1: Ngay cả gói nó trong việc sử dụng, tôi vẫn có thể nhìn thấy kết nối sử dụng (tôi đã kết nối tổng hợp tắt):

SELECT DB_NAME(dbid) as 'Database Name', 
COUNT(dbid) as 'Total Connections' 
FROM sys.sysprocesses WITH (nolock) 
WHERE dbid > 0 
GROUP BY dbid 

EDIT 2: Có một số lỗi hơn với giúp tôi nhận được từ đây - câu trả lời là ai đó đã mã hóa một chuỗi kết nối với việc gộp chung. Cảm ơn tất cả sự giúp đỡ - nếu có thể, tôi sẽ đánh dấu tất cả các câu trả lời là câu trả lời.

Trả lời

19

C# 's thu gom rác thải là không xác định nhưng ngôn ngữ không cung cấp một cấu trúc xác định để xử lý nguồn tài nguyên như thế này:

using (SqlConnection connection = new SqlConnection(...)) 
{ 
    // ... 
} 

này sẽ tạo ra một khối try/finally đó sẽ đảm bảo rằng các đối tượng kết nối được xử lý bất kể những gì xảy ra trong phương pháp. Bạn thực sự nên bao bọc bất kỳ trường hợp nào của các kiểu thực hiện IDisposable trong một khối sử dụng như nó sẽ đảm bảo quản lý tài nguyên có trách nhiệm (của các tài nguyên không được quản lý như kết nối cơ sở dữ liệu) và nó cũng mang lại cho bạn quyền kiểm soát xác định mà bạn đang tìm kiếm.

+0

+1 cho câu trả lời gọn gàng, tốt hơn so với tôi. –

1

Nó sẽ là, sau khi thu gom rác thực hiện công việc. Tương tự như vậy để mở một luồng tệp để viết mà không cần đóng nó. Nó có thể bị 'khóa' mặc dù các mã đã nằm ngoài phạm vi.

2

Vì C# là ngôn ngữ thu thập rác và việc thu thập rác không xác định. Thực tế của nó là của bạn sqlconnection xử lý. Bạn không thể chọn khi nào.

Kết nối Sql là tài nguyên giới hạn và bạn có thể dễ dàng tạo đủ tài nguyên để chạy hết. Viết nó như thay vì điều này:

internal static DataSet SelectDataSet(String commandText, DataBaseEnum dataBase) 
{ 
    var dataset = new DataSet(); 

    using (SqlConnection sqlc = dataBase == DataBaseEnum.ZipCodeDb 
          ? new SqlConnection(ConfigurationManager.AppSettings["ZipcodeDB"]) 
          : new SqlConnection(ConfigurationManager.AppSettings["WeatherDB"])) 
    using (SqlCommand sqlcmd = sqlc.CreateCommand()) 
    { 
     sqlcmd.CommandText = commandText; 
     var adapter = new SqlDataAdapter(sqlcmd.CommandText, sqlc); 
     adapter.Fill(dataset); 

    } 
    return dataset; 
} 

Mặc dù trong trường hợp này bạn có thể nhận được ngay với nó, bởi vì các .Fill() method is a strange beast:

Nếu IDbConnection được đóng trước khi Fill được gọi, nó được mở ra để lấy dữ liệu và sau đó đóng lại.

Vì vậy, điều đó có nghĩa là Bộ tiếp hợp dữ liệu sẽ xử lý nó cho bạn, nếu bạn bắt đầu với kết nối đã đóng. Tôi quan tâm nhiều hơn đến việc bạn đang truyền lệnh sql của bạn dưới dạng một chuỗi đơn giản. Đôi khi phải có tham số người dùng trong truy vấn của bạn và điều này có nghĩa là bạn đang ghép nối dữ liệu đó trực tiếp vào chuỗi lệnh. Đừng làm thế !! Sử dụng bộ sưu tập Paramters của SqlCommand thay thế.

1

Tôi tin rằng nó có liên quan đến việc gộp nhóm SqlConnection.Những gì bạn có thể làm, và chúng tôi thường xuyên làm việc là bọc toàn bộ cuộc gọi trong một tuyên bố sử dụng mà làm cho nó gọi phương thức vứt bỏ(), đóng kết nối và xử lý đối tượng

Sau đó bạn có thể làm điều gì đó như thay vào đó:


internal static DataSet SelectDataSet(String commandText, DataBaseEnum dataBase) 
{ 
    var dataset = new DataSet(); 

    using(SqlConnection sqlc = dataBase == DataBaseEnum.ZipCodeDb 
          ? new SqlConnection(ConfigurationManager.AppSettings["ZipcodeDB"]) 
          : new SqlConnection(ConfigurationManager.AppSettings["WeatherDB"])) { 
     SqlCommand sqlcmd = sqlc.CreateCommand(); 
     sqlcmd.CommandText = commandText; 
     var adapter = new SqlDataAdapter(sqlcmd.CommandText, sqlc); 
     adapter.Fill(dataset); 


     return dataset; 
    } 
} 

1

Tôi đồng ý với tất cả các câu trả lời ở đây cộng với kết nối có thể rộng hơn so với phương pháp. Khi bạn cần sử dụng kết nối hiện tại của bạn ở những nơi khác nhau, kịch bản thay đổi một chút. Luôn đảm bảo gọi số Dispose cho tất cả các đối tượng thực hiện IDisposable sau khi bạn sử dụng xong chúng. Đây là một thực hành tốt vì vậy bạn không kết thúc với các đối tượng không sử dụng mà các nhà sưu tập rác không thể quyết định phải làm gì với họ.

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