简体   繁体   English

正确处理DbConnection

[英]Properly disposing of a DbConnection

I have a class called DatabaseHelper that wraps a DbConnection. 我有一个名为DatabaseHelper的类,它包装了一个DbConnection。 What's the proper way to setup this class for a using statement? 为using语句设置此类的正确方法是什么? I have implemented IDisposible, but I'm not sure when and where I should be calling Connection.Close() or Connection.Dispose(). 我已经实现了IDisposible,但我不确定我应该何时何地调用Connection.Close()或Connection.Dispose()。

When I simply call Connection.Dispose() in my own Dispose() method, I'll sometimes get a SocketException from my DbConnection object. 当我在我自己的Dispose()方法中调用Connection.Dispose()时,我有时会从我的DbConnection对象中获取SocketException。 I assume this is because old connections are being left open, but there's no details attached the to exception, so I can't know for sure. 我认为这是因为旧的连接处于打开状态,但没有附加到异常的详细信息,所以我无法确定。

Call connection.Dispose() from within your dispose method. 从dispose方法中调用connection.Dispose()。 You should look at the standard pattern for implementing IDisposable, which goes above and beyond simply implementing the IDisposable interface and allows for disposing unmanaged objects etc: 您应该看一下实现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);
}

(Taken from http://msdn.microsoft.com/en-us/library/system.idisposable.aspx ). (摘自http://msdn.microsoft.com/en-us/library/system.idisposable.aspx )。

According to this newsgroup: 根据这个新闻组:

Here is how IDbConnection.Dispose() is implemented (as Reflector utility shows): 以下是IDbConnection.Dispose()的实现方式(如Reflector实用程序所示):

SqlClient: 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);
}

Your dispose method should only attempt to close the connection if it is open. 您的dispose方法只应尝试在打开时关闭连接。

This destructor syntax is actualy the finalizer. 这个析构函数语法实际上是终结器。 The finalizer is calling Dispose(false) method. 终结器调用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

There is no need of the finalizer(or destructor) syntax until your code has part 2 code . 代码具有第2部分代码之前, 不需要终结器(或析构函数)语法。 Otherwise it should be implemented for the safe side. 否则应该为安全起见而实施。 ie, even though the programmer is not calling the dispose method properly, finalize should clean up the unmanaged resources. 即,即使程序员没有正确调用dispose方法,finalize也应该清理非托管资源。

compare the examples: From msdn 比较示例:来自msdn

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

Just to complete the IDisposable implementation pattern, it's convention to include a finalizer (destructor) for your class which calls the Dispose() method (passing false). 只是为了完成IDisposable实现模式,通常为您的类包含一个终结器(析构函数),它调用Dispose()方法(传递false)。 This acts as a failsafe mechanism, allowing you to dispose of unmanaged objects if the consumer of the class fails to call Dispose(). 这充当故障保护机制,如果类的使用者无法调用Dispose(),则允许您处置非托管对象。

    ~MyClass() 
    {
        Dispose(false);
    }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM