Domanda

Ho una classe chiamata DatabaseHelper che avvolge una DbConnection. Qual è il modo corretto di impostare questa classe per un'istruzione using? Ho implementato IDisposible, ma non sono sicuro quando e dove dovrei chiamando connection.Close () o Connection.Dispose ().

Quando ho semplicemente chiamare Connection.Dispose () nel mio metodo proprio Dispose (), io a volte ottenere un SocketException dal mio oggetto DbConnection. Presumo che ciò è dovuto al fatto vecchie connessioni vengono lasciati aperti, ma non c'è nessun dettaglio attaccato l'ad eccezione, quindi non posso sapere con certezza.

È stato utile?

Soluzione

Chiama connection.Dispose () dall'interno del metodo Dispose. Si dovrebbe guardare al modello standard per l'attuazione IDisposable, che va al di là semplicemente implementando l'interfaccia IDisposable e permette per lo smaltimento di oggetti non gestiti 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);
}

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

Altri suggerimenti

questo newsgroup :

Ecco come viene implementato IDbConnection.Dispose () (come spettacoli di utilità 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);
}

Il metodo dispose deve solo tentare di chiudere la connessione se è aperto.

Questa sintassi distruttore è actualy il finalizzatore. Il finalizzatore sta chiamando Dispose (false) metodo.

    #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

non è necessario della sintassi finalizzatore (o distruttore) fino a quando il codice ha parte 2 codice . Altrimenti dovrebbe essere attuato per il lato sicurezza. vale a dire, anche se il programmatore non chiama il metodo corretto smaltimento, finalizzare dovrebbe ripulire le risorse non gestite.

confrontare gli esempi: da MSDN

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

Proprio per completare lo schema di attuazione IDisposable, è convenzione per includere un finalizzatore (distruttore) per la classe che chiama il metodo Dispose () (passando false). Questo agisce come un meccanismo di sicurezza, che consente di smaltire oggetti non gestiti se il consumatore della classe non riesce a chiamare Dispose ().

    ~MyClass() 
    {
        Dispose(false);
    }
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top