Tôi có cần sử dụng try-finally
hoặc using
để tránh xử lý SqlTransaction
?
Nó không đau khi có nó. Điều này đúng với mọi lớp thực hiện IDisposable, nếu không nó sẽ không thực hiện giao diện này.
Nhưng thông thường, bộ thu gom rác sẽ xử lý nếu đối tượng không được tham chiếu nữa. Bởi vì tôi cũng không muốn gọi dispose
trên mỗi biến thứ hai hoặc sử dụng using-statement ở khắp mọi nơi, nên luôn xem xét việc triển khai thực tế phương thức 'Dispose
' của lớp học.
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);
}
Nếu không có sự hiểu biết tất cả (hoặc bất cứ điều gì) những gì đang xảy ra ở đây tôi có thể nói rằng đây không chỉ là một đơn giản base.Dispose(disposing)
. Vì vậy, nó có thể là một ý tưởng tốt để đảm bảo rằng một SqlTransaction được xử lý.
Nhưng vì SqlConnection.BeginTransaction
tạo giao dịch nó cũng có thể là một ý tưởng tốt để reflect này cũng:
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;
}
Như bạn có thể nhìn thấy. Các GC cũng sẽ giữ cho kết nối còn sống khi một giao dịch được tạo ra. Nó cũng không giữ một tham chiếu đến giao dịch vì nó chỉ trả về nó. Do đó nó có thể không được xử lý ngay cả khi kết nối đã được xử lý. Một đối số khác để vứt bỏ giao dịch.
Bạn cũng có thể xem số TransactionScope
class an toàn hơn BeginTransaction
. Hãy xem this question để biết thêm thông tin.
Nguồn
2012-03-01 23:18:23
không làm tổn thương. – Brian
Nếu bạn không sử dụng 'using' xung quanh' sqlTrans' thì chắc chắn nó không bị tổn thương để gọi rõ ràng 'Dispose()' trên nó. –
@Cory Có cần kiểm tra xem sqlTrans đã được xử lý trước khi gọi sqlTrans.Dispose() chưa? – Lijo