Правильное удаление DbConnection - PullRequest
2 голосов
/ 22 декабря 2008

У меня есть класс DatabaseHelper, который оборачивает DbConnection. Как правильно настроить этот класс для оператора using? Я реализовал IDisposible, но я не уверен, когда и где мне следует вызывать Connection.Close () или Connection.Dispose ().

Когда я просто вызываю Connection.Dispose () в своем собственном методе Dispose (), я иногда получаю исключение SocketException от моего объекта DbConnection. Я предполагаю, что это потому, что старые соединения остаются открытыми, но нет никаких деталей, связанных с исключением, поэтому я не могу знать наверняка.

Ответы [ 4 ]

6 голосов
/ 22 декабря 2008

Вызовите соединение. Dispose () из вашего метода 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 голосов
/ 22 декабря 2008

Согласно этой группе новостей:

Вот как реализован 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);
}

Ваш метод удаления должен пытаться закрыть соединение, только если оно открыто.

1 голос
/ 04 июля 2013

Этот синтаксис деструктора фактически является финализатором. Финализатор вызывает 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

0 голосов
/ 22 декабря 2008

Просто для завершения шаблона реализации IDisposable принято включать финализатор (деструктор) для вашего класса, который вызывает метод Dispose () (передавая false). Это действует как отказоустойчивый механизм, позволяющий избавляться от неуправляемых объектов, если потребитель класса не может вызвать Dispose ().

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