Former. If you look up MSDN samples on similar topics, like TransactionScope
, they all favor the implicit rollback. There are various reasons for that, but I'll just give you a very simple one: by the time you catch the exception, the transaction may had already rolled back. Many errors rollback the pending transaction and then they return control to the client, where the ADO.Net raises the CLR SqlException after the transaction was already rolled back on the server (1205 DEADLOCK is the typical example of such an error), so the explicit Rollback()
call is, at best, a no-op, and at worse an error. The provider of the DbTransaction
(eg. SqlTransaction
) should know how to handle this case, eg. because there is explicit chat between the server and the client notifying of the fact that the transaction rolled back already, and the Dispose()
method does the right thing.
A second reason is that transactions can be nested, but the semantics of ROLLBACK are that one rollback rolls back all transactions, so you only need to call it once (unlike Commit()
which commits only the inner most transaction and has to be called paired up for each begin). Again, Dispose()
does the right thing.
Update
The MSDN sample for SqlConnection.BeginTransaction()
actually favors the second form and does an explicit Rollback()
in the catch
block. I suspect the technical writer simply intended to show in one single sample both Rollback()
and Commit()
, notice how he needed to add a second try/catch block around the Rollback
to circumvent exactly some of the problems I mentioned originally.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…