2008-12-22 109 views
2

我有一個名爲DatabaseHelper的類,它包裝了一個DbConnection。爲使用語句設置此類的正確方法是什麼?我已經實現了IDisposible,但我不確定何時何地應該調用Connection.Close()或Connection.Dispose()。正確處理DbConnection

當我在自己的Dispose()方法中簡單調用Connection.Dispose()時,有時會從我的DbConnection對象中獲取SocketException。我認爲這是因爲舊的連接被打開,但沒有任何細節附加到例外,所以我無法確定。

+0

刪除GC標籤,因爲這是不是真的與普通垃圾收集.NET。 – 2008-12-22 20:15:13

回答

6

從你的dispose方法中調用connection.Dispose()。你應該看看在標準模式實現IDisposable的,它去超越簡單地實現IDisposable接口,並允許處置非託管對象等:

public void Dispose() 
{ 
    Dispose(true); 
    GC.SuppressFinalize(this); 
} 

protected virtual void Dispose(bool disposing) 
{ 
    if (!disposed) 
    { 
     if (disposing) 
     { 
      // Dispose managed resources. 
     } 

     // There are no unmanaged resources to release, but 
     // if we add them, they need to be released here. 
    } 
    disposed = true; 

    // If it is available, make the call to the 
    // base class's Dispose(Boolean) method 
    base.Dispose(disposing); 
} 

(從http://msdn.microsoft.com/en-us/library/system.idisposable.aspx兩者)​​。

+0

我的2美分:數據庫連接是非託管資源。 – 2011-03-01 10:45:58

2

根據this新聞組:

這裏是IDbConnection.Dispose()如何實現(如反射實用所示):

的SqlClient:

protected override void Dispose(bool disposing) 
{ 
     if (disposing) 
     { 
      switch (this._objectState) 
      { 
        case ConnectionState.Open: 
        { 
         this.Close(); 
         break; 
        } 
      } 
      this._constr = null; 
     } 
     base.Dispose(disposing); 
} 

Odbc: 
protected override void Dispose(bool disposing) 
{ 
     if (disposing) 
     { 
      this._constr = null; 
      this.Close(); 
      CNativeBuffer buffer1 = this._buffer; 
      if (buffer1 != null) 
      { 
        buffer1.Dispose(); 
        this._buffer = null; 
      } 
     } 
     base.Dispose(disposing); 
} 

OleDb: 
protected override void Dispose(bool disposing) 
{ 
     if (disposing) 
     { 
      if (this.objectState != 0) 
      { 
        this.DisposeManaged(); 
        if (base.DesignMode) 
        { 
         OleDbConnection.ReleaseObjectPool(); 
        } 
        this.OnStateChange(ConnectionState.Open, ConnectionState.Closed); 
      } 
      if (this.propertyIDSet != null) 
      { 
        this.propertyIDSet.Dispose(); 
        this.propertyIDSet = null; 
      } 
      this._constr = null; 
     } 
     base.Dispose(disposing); 
} 

你的Dispose方法應該只嘗試如果它打開,請關閉連接。

0

只是爲了完成IDisposable實現模式,約定爲您的類添加一個調用Dispose()方法(傳遞false)的終結器(析構函數)。這充當故障安全機制,如果該類的使用者未能調用Dispose(),則允許您處置非託管對象。

~MyClass() 
    { 
     Dispose(false); 
    } 
1

這個析構函數語法實際上就是終結器。終結器調用Dispose(false)方法。

#region IDisposable Members 
    private bool _isDisposed; 

    private void ThrowIfDisposed() 
    { 
     if (_isDisposed) 
      throw new ObjectDisposedException(this.GetType().Name); 
    } 

    protected virtual void Dispose(bool disposing) 
    { 
     if (!_isDisposed) 
     { 
      if (disposing) 
      { 
       //part 1 : disposing managed objects 
       _command.Dispose(); 
       _command.Connection.Dispose(); 
       if (_command.Transaction != null) 
        _command.Transaction.Dispose(); 
      } 
      //part 2: disposing unmanged objects. Here there are no unmanged objects. 
      _isDisposed = true; 
     } 
    } 

    public void Dispose() 
    { 
     Dispose(true); 
     GC.SuppressFinalize(this); 
    } 

    //~DbCommandExecutor() //No need of finalize here. Because there is no unmanged objects in my class. ie, no code in part 2. 
    //{ 
    // Dispose(false); 
    //} 
    #endregion 

沒有終結(或析構函數)語法的需要,直到你的代碼中有部分2碼。否則,應該爲安全起見而實施。即,即使程序員沒有正確調用dispose方法,finalize也應該清理非託管資源。

比較的例子:從MSDN

http://msdn.microsoft.com/en-us/library/system.idisposable.dispose.aspx & http://msdn.microsoft.com/en-us/library/fs2xkftw.aspx