Нужно ли использовать try-finally
или using
заявление для распоряжения SqlTransaction
?
Это не помешает иметь его.Это верно для каждого класса, реализующего IDisposable , в противном случае он не будет реализовывать этот интерфейс.
Но обычно сборщик мусора будет иметь дело с ним, если на объект больше не будут ссылаться.Поскольку я также не хочу вызывать dispose
для каждой второй переменной или везде использовать using-оператор , всегда стоит взглянуть на фактическую реализацию метода класса Dispose
.
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);
}
Не понимая всего (или чего-либо), что здесь происходит, я могу сказать, что это больше, чем просто base.Dispose(disposing)
.Поэтому может быть хорошей идеей обеспечить удаление SqlTransaction.
Но поскольку SqlConnection.BeginTransaction
создает транзакцию, также может быть хорошей идеей отразить это также:
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;
}
Как видите. GC также будет поддерживать соединение в действии при создании транзакции.Он также не содержит ссылку на транзакцию, поскольку он только возвращает ее.Следовательно, он не может быть утилизирован, даже если соединение уже удалено.Еще один аргумент для удаления транзакции.
Вы также можете взглянуть на TransactionScope
класс , который более надежен, чем BeginTransaction
.Посмотрите этот вопрос для получения дополнительной информации.