Ho bisogno di usare try-finally
o using
-affermazione di smaltire il SqlTransaction
?
Non fa male averlo. Questo è vero per ogni classe che implementa IDisposable, altrimenti non implementerebbe questa interfaccia.
Ma normalmente il garbage collector si occuperà di esso se l'oggetto non viene più referenziato. Perché anche io non voglio chiamare dispose
su ogni seconda variabile o utilizzare il using-statement ovunque, vale sempre la pena di esaminare l'effettiva implementazione del metodo 'Dispose
della classe'.
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);
}
Senza capire tutto (o niente) ciò che sta accadendo qui posso dire che questo è più di un semplice base.Dispose(disposing)
. Quindi potrebbe essere una buona idea assicurarsi che un SqlTransaction venga eliminato.
Ma perché SqlConnection.BeginTransaction
crea la transazione potrebbe anche essere una buona idea per reflect anche questo:
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;
}
Come si può vedere. Lo GC manterrà la connessione attiva anche quando viene creata una transazione. Inoltre, non tiene un riferimento alla transazione poiché la restituisce solo. Quindi potrebbe non essere disposto anche quando la connessione è già disponibile. Un altro argomento per disporre la transazione.
Si potrebbe anche dare un'occhiata al TransactionScope
class che è più sicuro rispetto a BeginTransaction
. Date un'occhiata a this question per maggiori informazioni.
fonte
2012-03-01 23:18:23
non fa male ad averlo. – Brian
Se non si sta usando un 'using' su' sqlTrans', allora certamente non fa male chiamare esplicitamente 'Dispose()'. –
@Cory E 'necessario verificare se sqlTrans è già eliminato prima di chiamare sqlTrans.Dispose()? – Lijo