2008-09-26 77 views
18

我使用的模式看起來像這樣經常。我想知道這是否正常,或者是否有我不在這裏申請的最佳做法。當引發異常時,確保SQL連接關閉的正確方法是什麼?

具體我想知道;在引發異常的情況下,我在finally塊中的代碼足以確保連接適當關閉?

public class SomeDataClass : IDisposable 
{ 
    private SqlConnection _conn; 

    //constructors and methods 

    private DoSomethingWithTheSqlConnection() 
    { 
     //some code excluded for brevity 

     try 
     { 
      using (SqlCommand cmd = new SqlCommand(SqlQuery.CountSomething, _SqlConnection)) 
      { 
       _SqlConnection.Open(); 
       countOfSomething = Convert.ToInt32(cmd.ExecuteScalar()); 
      } 
     } 
     finally 
     { 
      //is this the best way? 
      if (_SqlConnection.State == ConnectionState.Closed) 
       _SqlConnection.Close(); 
     } 

     //some code excluded for brevity 
    } 

    public Dispose() 
    { 
     _conn.Dispose(); 
    } 
} 
+1

呃......你爲什麼要檢查的連接關閉之前已經關閉?爲什麼使用類成員來存儲連接,如果你要使用它的唯一方法關閉它? – Shog9 2008-09-26 18:46:33

+1

spoon16包含短語「//爲了簡潔排除某些代碼」。由此我推斷這不是使用它的唯一方法。 – 2008-09-26 18:52:41

+0

是正確的,這絕對是我能想到的最簡單的例子。我認爲,由於連接池,我不需要嘗試存儲每個方法範圍之外的SqlConnection對象。所以只要使用USING作爲其他建議。 – 2008-09-26 20:19:35

回答

45

總結你的數據庫處理代碼內部的 「使用」

using (SqlConnection conn = new SqlConnection (...)) 
{ 
    // Whatever happens in here, the connection is 
    // disposed of (closed) at the end. 
} 
1

由於您使用IDisposables反正。你可以使用'using'關鍵字,它基本上等同於在finally塊中調用dispose,但它看起來更好。

2

我猜,通過「_SqlConnection.State == ConnectionState.Closed」你的意思!=。

這肯定會起作用。我認爲習慣上把連接對象本身包含在using語句中,但是如果你想由於某種原因重用相同的連接對象,你所擁有的就很好。

但是,您應該改變的一件事是Dispose()方法。您不應該在處理中引用連接對象,因爲它可能已經在此處完成。您應該遵循推薦的Dispose模式。

-4

我可以建議是:


    class SqlOpener : IDisposable 
    { 
     SqlConnection _connection; 

     public SqlOpener(SqlConnection connection) 
     { 
      _connection = connection; 
      _connection.Open(); 

     } 

     void IDisposable.Dispose() 
     { 
      _connection.Close(); 
     } 
    } 

    public class SomeDataClass : IDisposable 
    { 
     private SqlConnection _conn; 

     //constructors and methods 

     private void DoSomethingWithTheSqlConnection() 
     { 
      //some code excluded for brevity 
      using (SqlCommand cmd = new SqlCommand("some sql query", _conn)) 
      using(new SqlOpener(_conn)) 
      { 
       int countOfSomething = Convert.ToInt32(cmd.ExecuteScalar()); 
      } 
      //some code excluded for brevity 
     } 

     public void Dispose() 
     { 
      _conn.Dispose(); 
     } 
    } 

希望幫助:)

1

把連接關閉代碼「最後」塊內像你這樣的表現。最後,塊在執行異常之前執行。使用「使用」塊也可以,但我發現明確的「最後」方法更清晰。

對許多開發人員來說,使用語句是老生常談,但年輕的開發人員可能不知道這一點。

8

.Net Framework保持連接池的原因。相信它! :) 只需連接到數據庫並釋放連接,就不必編寫太多的代碼。

您可以使用'using'語句並放心'IDBConnection.Release()'將爲您關閉連接。

高度詳盡的「解決方案」往往會導致錯誤的代碼。簡單更好。

5

MSDN Docs就能很清楚......

  • Close方法回滾任何未決的事務。然後它釋放到連接池的連接,或者在連接池被禁用時關閉連接。

您可能沒有(也不希望)禁用連接池,因此池調用「關閉」後最終管理連接狀態。這可能很重要,因爲在所有打開的連接中從數據庫服務器端查看可能會感到困惑。


  • 應用程序可以調用關閉超過一次。沒有異常產生。

那麼爲什麼麻煩測試閉?只需調用Close()。


  • 關閉和處置在功能上等同。

這就是爲什麼使用塊導致關閉連接。 使用來電爲您處置。


  • 不要調用關閉或Dispose一個連接,一個DataReader或在您的類的Finalize方法的任何其他託管對象。

重要的安全提示。謝謝,埃貢。

1

的答案見這個問題:

Close and Dispose - which to call?

如果您的連接一生是一個單一的方法調用,使用的語言的using功能,以確保連接的正確清理。雖然try/finally功能塊在功能上相同,但它需要更多的代碼,並且IMO的可讀性較差。不需要檢查連接的狀態,不管怎樣,您都可以撥打Dispose來清理連接。

如果您的連接生存期對應於包含類的生存期,則執行IDisposable並清理Dispose中的連接。

0

不需要一個try..finally圍繞一個「使用」,使用的IS 一個 try..finally

相關問題