Правильное удаление DbConnection

2

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

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

  • 0
    Удален тег GC, так как он на самом деле не связан с обычной сборкой мусора в .NET.
Теги:
dispose

4 ответа

6
Лучший ответ

Вызовите соединение. Задайте() из вашего метода 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 Dispose(Boolean) method
    base.Dispose(disposing);
}

(взято из http://msdn.microsoft.com/en-us/library/system.idisposable.aspx).

  • 0
    Мои 2 цента: соединение с БД - неуправляемый ресурс.
2

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

Вот как реализуется 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 должен только пытаться закрыть соединение, если он открыт.

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. В противном случае он должен быть реализован для безопасной стороны. т.е. даже если программист не вызывает метод удаления правильно, финализация должна очистить неуправляемые ресурсы.

сравните примеры: из msdn

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

0

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

    ~MyClass() 
    {
        Dispose(false);
    }

Ещё вопросы

Сообщество Overcoder
Наверх
Меню