【问题标题】:Properly disposing of a DbConnection正确处理 DbConnection
【发布时间】:2010-09-28 01:21:34
【问题描述】:

我有一个名为 DatabaseHelper 的类,它包装了一个 DbConnection。为 using 语句设置此类的正确方法是什么?我已经实现了 IDisposible,但我不确定应该在何时何地调用 Connection.Close() 或 Connection.Dispose()。

当我在自己的 Dispose() 方法中简单地调用 Connection.Dispose() 时,有时我会从我的 DbConnection 对象中得到一个 SocketException。我认为这是因为旧连接处于打开状态,但没有附加到异常的详细信息,所以我不能确定。

【问题讨论】:

  • 删除了 GC 标签,因为这与 .NET 中的常规垃圾收集没有真正的关系。

标签: c# dispose dbconnection


【解决方案1】:

在你的 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)。

【讨论】:

    【解决方案2】:

    this新闻组:

    以下是 IDbConnection.Dispose() 的实现方式(如 Reflector 实用程序所示):

    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 方法应该只在连接打开时尝试关闭它。

    【讨论】:

      【解决方案3】:

      这个析构函数语法实际上是终结器。终结器正在调用 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

      【讨论】:

        【解决方案4】:

        为了完成 IDisposable 实现模式,约定为您的类包含一个终结器(析构函数),该终结器调用 Dispose() 方法(传递 false)。这充当了一种故障安全机制,允许您在类的使用者未能调用 Dispose() 时处置非托管对象。

            ~MyClass() 
            {
                Dispose(false);
            }
        

        【讨论】:

          猜你喜欢
          • 2011-01-29
          • 2015-03-19
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2016-07-15
          • 2015-09-18
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多