2009-07-21 44 views
5

Tôi có mã dưới đây để truy vấn hồ sơ từ một thủ tục đã lưu trữ nhưng có liên quan tôi có thể không xử lý những gì tôi cần hoặc đang xử lý khi đối tượng sẽ bị xóa bởi Garbage Collector ngay sau đó.C# sql gì cần vứt bỏ

Tôi có cần phải vứt bỏ SqlDataReader vì nó nằm trong khối try catch không?

Tôi có cần chạy cả cmd.Dispose và cmd.Connection.Close hay không suy luận cái kia?

Nhà sưu tập rác cuối cùng sẽ xử lý tất cả các đối tượng này (có thể không đủ kịp thời) hoặc các đối tượng này có đòi hỏi phải vứt bỏ có thể do sử dụng mã không được quản lý không?

public void GetData(string studentID) 
    { 
     SqlCommand cmd = new SqlCommand("sp_stored_proc", 
       new SqlConnection(Settings.Default.connectionString)) 
       { CommandType = CommandType.StoredProcedure }; 
     try 
     { 
      cmd.Connection.Open(); 
      cmd.Parameters.AddWithValue("@student_id", studentID); 
      SqlDataReader dr = cmd.ExecuteReader(); 

     //do something with the data 

      if (dr != null) 
       dr.Dispose(); 
     } 
     catch 
     { 
      //error handling 
     } 
     finally 
     { 
      if (cmd != null) 
      { 
       cmd.Dispose(); 
       cmd.Connection.Close(); 
      } 

     } 

    } 

Trả lời

16

Bạn nên bỏ thiết bị đọc dữ liệu và lệnh. Không cần phải đóng riêng kết nối nếu bạn vứt bỏ lệnh. Bạn lý tưởng nên làm cả hai sử dụng một khối using:

using (SqlCommand cmd = new...) 
{ 
    // do stuff 
    using (SqlDataReader dr = cmd.ExecuteReader()) 
    { 
     // do stuff 
    } 
} 

Nếu bạn cần xử lý ngoại lệ làm điều đó một cách riêng biệt hoặc bên trong hoặc xung quanh các khối sử dụng - không có nhu cầu sử dụng cuối cùng cho Dispose cuộc gọi mặc dù với using.

+1

Nếu tôi có thể upvote điều này nhiều hơn một lần, tôi sẽ. BẮT ĐẦU VÀO NGƯỜI! SỬ DỤNG SỬ DỤNG KHÓA! –

+2

Việc hủy bỏ đối tượng 'SqlCommand' sẽ không ** hủy bỏ' SqlConnection'. Điều này rất dễ dàng để kiểm tra. http://stackoverflow.com/questions/60919/is-sqlcommand-dispose-enough/60934#60934 – arcain

+0

Tôi có phải vứt bỏ người đọc ngay cả khi tôi vứt bỏ lệnh không? Tôi có phải vứt bỏ lệnh ngay cả khi tôi bỏ kết nối không? Bạn có thể giới thiệu chúng tôi với bất kỳ nguồn nào trong số này không? – Lii

3

Tôi có cần phải vứt bỏ SqlDataReader vì nó nằm trong cố gắng nắm bắt khối?

- Có, như bên trong thử bắt sẽ không gọi phương thức vứt bỏ.

Tôi có cần chạy cả hai cmd.Dispose và cmd.Connection.Close hay không suy luận cái kia?

- Có, bạn cần phải chạy cả hai. Gọi Cmd.dispose không đóng kết nối.

Phương pháp vứt bỏ có nghĩa là được sử dụng bởi lập trình viên để dọn sạch tài nguyên không được quản lý trực tiếp bởi bộ thu gom rác hoặc cần được xóa sau khi chương trình được thực hiện bằng cách sử dụng chúng để giải phóng dung lượng. Về mặt kỹ thuật, người ta có thể thiết lập chương trình để GC có thể xử lý nó, nhưng đó là một giả định tôi sẽ không làm, đặc biệt là khi lập trình viên viết lớp tiếp xúc phương pháp vứt bỏ cho bạn. Đặt lệnh trong một câu lệnh sử dụng có lẽ là con đường dễ nhất, bởi vì bạn biết nó sẽ bị xử lý khi mã rời khỏi vùng khai báo.

using (var connection = new Connection()) 
{ 
    using (var cmd = new Command()) 
    { 



    } 
} 
+0

"không, cmd.dispose sẽ đóng kết nối" - Tôi nghĩ điều đó không chính xác; theo như tôi biết, việc gọi Dispose trên lệnh không liên quan gì đến kết nối của nó. –

+0

@Kevin: bài đăng bạn đã liên kết với các tiểu bang gọi là Vứt bỏ trên một đối tượng * kết nối * sẽ gọi gần trên cùng một đối tượng đó. Từ "lệnh" không xuất hiện trên trang. –

+0

Tôi đọc sai bài đăng khi tôi kiểm tra lại. Bạn đúng. – kemiller2002

2

Cá nhân nếu có thứ gì đó có phương pháp vứt bỏ thì bạn nên sử dụng nó vì chúng sẽ ngăn chặn rò rỉ bộ nhớ.

3

Nếu bạn sử dụng một cái gì đó như thế này:

public void GetData(string studentID) 
{ 
    using (SqlConnection connection = new SqlConnection(Settings.Default.connectionString)) 
    { 
     connection.Open(); 

     using (SqlCommand command = connection.CreateCommand()) 
     { 
      command.CommandType = CommandType.StoredProcedure; 
      command.CommandText = "sp_stored_proc"; 
      command.Parameters.AddWithValue("@student_id", studentID); 

      using (SqlDataReader dataReader = command.ExecuteReader()) 
      { 
       // do something with the data 
      } 
     } 
    } 
} 

sau đó tất cả các đối tượng dùng một lần của bạn sẽ được xử lý một cách chính xác. Gọi Dispose() trên các đối tượng SqlConnection, SqlCommand và SqlDataReader (đó là những gì khối sử dụng thực hiện khi nó thoát) đóng chúng một cách chính xác.

Ngoài ra, cách tiếp cận này giữ tất cả các biến của bạn được dò tìm ở nơi chúng được sử dụng.Nhược điểm của phương pháp này là nếu bạn cần xử lý lỗi bằng cách sử dụng try/catch, bạn phải quấn xung quanh toàn bộ phương thức hoặc sử dụng một vài trong số chúng để xử lý lỗi kết nối khác với lỗi đọc, v.v. ..

1

Để tạo một câu chuyện dài; nếu nó triển khai IDisposable, bạn nên gọi Dispose.

Thậm chí nếu bạn sử dụng Reflector để tìm ra rằng Dispose trong một đối tượng gọi Dispose trên đối tượng khác, tôi vẫn muốn giới thiệu để gọi Dispose trên cả hai, vì đây là chi tiết thực hiện nội bộ mà có thể thay đổi trong một số phiên bản trong tương lai, vì vậy bạn không nên dựa vào điều đó luôn đúng.

Vì vậy, Dispose mọi thứ là IDisposable.

-4

bạn nên mở Kết nối trước hết bằng Connection.Open(); sau đó sử dụng các phương pháp như SqlDataReader để đọc sau khi tất cả, SqlDataReader gần trước hết và sau đó kết nối chặt chẽ

bạn có thể sử dụng từ khóa "sử dụng" để vứt bỏ nó, nhưng nó không phải là một ý tưởng tốt

trong thực tế, từ khóa "sử dụng" là tự động xử lý đối tượng. nói cách khác, đối tượng cần đạt được phương pháp vứt bỏ

+0

-1 bạn đang nói sử dụng các khối là một ý tưởng tồi? –

+0

Vui lòng giải thích lý do tại sao cấu trúc sử dụng là ý tưởng tồi trong trường hợp này. – LOAS

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