Pergunta

Eu tenho uma classe chamada DatabaseHelper que envolve um DbConnection. O que é a maneira correta de configurar esta classe para um usando instrução? Eu tenho implementado IDisposible, mas eu não tenho certeza de quando e onde eu deveria estar chamando Connection.Close () ou Connection.Dispose ().

Quando eu simplesmente chamar Connection.Dispose () no meu próprio método Dispose (), eu vou, por vezes, obter um SocketException do meu objeto DbConnection. Suponho que isso é porque as antigas conexões estão sendo deixadas em aberto, mas não há detalhes anexados à exceção, então não posso saber com certeza.

Foi útil?

Solução

Chamada connection.Dispose () de dentro do seu método de descarte. Você deve olhar para o padrão padrão para implementar IDisposable, que vai acima e além de simplesmente implementar a interface IDisposable e permite descartar objetos não gerenciados etc:

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

(Tomado de http://msdn.microsoft.com/en -us / library / system.idisposable.aspx ).

Outras dicas

De acordo com a este newsgroup :

Aqui está como IDbConnection.Dispose () é implementado (como mostra a utilidade do refletor):

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

Seu método dispose só deve tentar fechar a conexão se ele estiver aberto.

Esta sintaxe destruidor é actualy o finalizador. O finalizador está chamando Dispose (false) método.

    #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

Existe não há necessidade do finalizador (ou destruidor) sintaxe até que seu código tem parte 2 código . Caso contrário, ele deve ser implementado para o lado seguro. ou seja, mesmo que o programador não está chamando o método de descartar corretamente, finalize deve limpar os recursos não gerenciados.

comparar os exemplos: do MSDN

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

Apenas para completar o padrão implementação IDisposable, é convenção para incluir um finalizador (destructor) para sua classe que chama o (falso passando) Método Dispose (). Isto age como um mecanismo de segurança, o que lhe permite dispor de objetos não gerenciados se o consumidor da classe não chamar Dispose ().

    ~MyClass() 
    {
        Dispose(false);
    }
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top