Вопрос

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

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

Это было полезно?

Решение

Вызовите 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).

Другие советы

В соответствии с этот группа новостей:

Вот как реализован IDbConnection.Dispose() (как показывает утилита Reflector):

СклКлиент:

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

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

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

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

    ~MyClass() 
    {
        Dispose(false);
    }
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top