Question

Dois-je appeler Disser dans le bloc enfin pour SQLTRansaction? Imaginez que le développeur n'utilisait en utilisant nulle part et essayez / attrapez / attrape.

SqlTransaction sqlTrans = con.BeginTransaction();

try
{
     //Do Work
sqlTrans.Commit()
}
catch (Exception ex)
        {

           sqlTrans.Rollback();
        }

 finally
        {
            sqlTrans.Dispose();
            con.Dispose();
        }
Était-ce utile?

La solution

Dois-je utiliser try-finally ou la using-Sédition pour disposer le SqlTransaction?

Cela ne fait pas de mal de l'avoir. Cela est vrai pour chaque mise en œuvre de classe Idisposable, Sinon, il n'implémenterait pas cette interface.

Mais normalement, le collecteur des ordures le traiterait si l'objet n'est plus référencé. Parce que je ne veux pas non plus appeler dispose à chaque seconde variable ou utilisez le Utilisation de stades Partout, il vaut toujours la peine d'examiner la mise en œuvre réelle de la classe ' Dispose méthode.

SqlTransaction.Dispose:

protected override void Dispose(bool disposing)
{
    if (disposing)
    {
        SNIHandle target = null;
        RuntimeHelpers.PrepareConstrainedRegions();
        try
        {
            target = SqlInternalConnection.GetBestEffortCleanupTarget(this._connection);
            if (!this.IsZombied && !this.IsYukonPartialZombie)
            {
                this._internalTransaction.Dispose();
            }
        }
        catch (OutOfMemoryException e)
        {
            this._connection.Abort(e);
            throw;
        }
        catch (StackOverflowException e2)
        {
            this._connection.Abort(e2);
            throw;
        }
        catch (ThreadAbortException e3)
        {
            this._connection.Abort(e3);
            SqlInternalConnection.BestEffortCleanup(target);
            throw;
        }
    }
    base.Dispose(disposing);
}

Sans comprendre tout (ou quoi que ce soit) ce qui se passe ici, je peux dire que c'est plus qu'un simple base.Dispose(disposing). Il pourrait donc être une bonne idée de s'assurer qu'un SQLTransaction est éliminé.

Mais parce que SqlConnection.BeginTransaction crée la transaction, il pourrait également être une bonne idée de refléter ça aussi:

public SqlTransaction BeginTransaction(IsolationLevel iso, string transactionName)
{
    SqlStatistics statistics = null;
    string a = ADP.IsEmpty(transactionName) ? "None" : transactionName;
    IntPtr intPtr;
    Bid.ScopeEnter(out intPtr, "<sc.SqlConnection.BeginTransaction|API> %d#, iso=%d{ds.IsolationLevel}, transactionName='%ls'\n", this.ObjectID, (int)iso, a);
    SqlTransaction result;
    try
    {
        statistics = SqlStatistics.StartTimer(this.Statistics);
        SqlTransaction sqlTransaction = this.GetOpenConnection().BeginSqlTransaction(iso, transactionName);
        GC.KeepAlive(this);
        result = sqlTransaction;
    }
    finally
    {
        Bid.ScopeLeave(ref intPtr);
        SqlStatistics.StopTimer(statistics);
    }
    return result;
}

Comme tu peux le voir. La GC maintiendra également la connexion en vie lors de la création d'une transaction. Il ne détient pas non plus de référence à la transaction car il ne le renvoie. Par conséquent, il peut ne pas être disposé même lorsque la connexion est déjà disposée. Un autre argument pour éliminer la transaction.

Vous pourriez également jeter un œil au TransactionScope classer ce qui est plus sûr que BeginTransaction. Jettes un coup d'oeil à cette question pour plus d'informations.

Autres conseils

Dans le cas général, chaque IDisposable Objet que vous construisez ou obtenez, et possédez, vous devez éliminer.

Dans le cas spécifique, il y a quelques exceptions, mais SqlTransaction n'est pas l'un d'eux.

Selon le la documentation de SqlTransaction.Dispose:

Libère le Ressources non gérées Utilisé par le DBTransaction et libère éventuellement les ressources gérées.

(mon accent)

Étant donné que la documentation ne stipule pas que ces ressources non gérées sont publiées lorsque vous émettez un commit ou un retour en arrière, vous devrez éliminer cet objet.

Je pense que vous pouvez simplement clôturer la connexion. J'ai vérifié le code de BCL - semble que les connexions s'occupent de sa transaction - pas besoin de la fermer explicitement.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top