2016-03-03 37 views
0

我已閱讀有關使用Using子句時顯式關閉和/或處置IDisposable對象的衝突信息。C#SQL連接,命令和使用語句 - 顯式關閉和處置,或不?

從我的理解:

using (x) { .... } 

在編譯時被改寫爲:

try { .... } finally { if (x != null) x.Dispose(); } 

這意味着調用Dispose馬上在使用塊結束,對不對?

即使使用Using子句,有些人建議顯式調用close和/或dispose,因爲可能有一些延遲來等待Finally塊執行?

其他人說,在一個Using塊中調用Dispose總是多餘的。我傾向於同意,但我正在尋找一個明確的答案。

如果不使用使用子句,並且您沒有明確地關閉和處置,那麼垃圾回收(GC)是否會起作用?

以下面的方法爲例(請參閱註釋)。

public Musician GetMusician(int recordId) 
{ 
    Musician objMusician = null; 

    using(SqlConnection con = new SqlConnection(_connectionString)) 
    { 
     con.Open(); 
     using (SqlCommand cmd = new SqlCommand()) 
     { 
      cmd.Connection = con; 
      cmd.CommandText = "selectMusician"; 
      cmd.CommandType = CommandType.StoredProcedure; 
      cmd.Parameters.AddWithValue("@id", recordId); 

      using (SqlDataReader reader = cmd.ExecuteReader(CommandBehavior.CloseConnection)) 
      { 
       if (reader.HasRows) 
       { 
        reader.Read(); 
        objMusician = new Musician((int) reader["id"]); 
        objMusician.Name = (string) reader["name"]; 
       } 

       if objMusician != null) 
       { 
        objMusician.Albums = Albums.GetAlbums((int)objMusician.ID); 
        objMusician.Tours = Tours.GetTours((int)objMusician.ID); 
        objMusician.Interviews = Interviews.GetInterviews((int)objMusician.ID); 
       } 

       // do these two lines close and dispose of the reader any faster? 
       reader.Close(); 
       reader.Dispose(); 
      } 

      // does this line dispose of the command any faster? 
      cmd.Dispose(); 
     } 
     // do these two lines close and dispose of the connection any faster? 
     con.Close(); 
     con.Dispose(); 

     return objMusician; 
    } 
} 
+0

的使用塊的'SqlCommand'將被安置後,但尚未GC將收集它。 –

+0

除非您明確添加延遲,否則finally程序塊會在程序進入時直接執行。 –

回答

2

您正確描述了在塊使用結束時調用的Dispose方法。自定義對象的 https://msdn.microsoft.com/en-us/library/yh598w02.aspx

GC呼叫finalize()方法(未處置()直接地)在隨機的時間。 https://msdn.microsoft.com/en-us/library/system.object.finalize.aspx

通常Close方法在Dispose方法中包含它的不需要的調用,您必須閱讀具體類的文檔。

在你的情況我會改變代碼

public Musician GetMusician(int recordId) 
{ 
    Musician objMusician = null; 


    using(SqlConnection con = new SqlConnection(_connectionString)) 
     { 
      con.Open(); 
      using (SqlCommand cmd = new SqlCommand()) 
      { 
       cmd.Connection = con; 
       cmd.CommandText = "selectMusician"; 
       cmd.CommandType = CommandType.StoredProcedure; 
       cmd.Parameters.AddWithValue("@id", recordId); 

       using (SqlDataReader reader = cmd.ExecuteReader(CommandBehavior.CloseConnection)) 
       { 
        if (reader.HasRows) 
        { 
         reader.Read(); 
         objMusician = new Musician((int) reader["id"]); 
         objMusician.Name = (string) reader["name"]; 
        } 

        if objMusician != null) 
        { 
         objMusician.Albums = Albums.GetAlbums((int)objMusician.ID); 
         objMusician.Tours = Tours.GetTours((int)objMusician.ID); 
         objMusician.Interviews = Interviews.GetInterviews((int)objMusician.ID); 
        } 
       } 
      } 
     }  
    return objMusician; 
}