Question

What is the difference between System.Transactions.TransactionScope and EF6's Database.BeginTransaction?

Could someone give a small example or just explain which one to use when with a clear difference?

P.S: In my project, I'm using EF6. I've already read the documentation but it didn't help much. Also looked up the examples but they are rather using SqlConnection.BeginTransaction and now MS has introduced this new Database.BeginTransaction in EF6.

Was it helpful?

Solution

I found out the answer in Entity Framework 6's documentation:

With the introduction of EF6, Microsoft recommends to use new API methods: Database.BeginTransaction() and Database.UseTransaction(). Although System.Transactions.TransactionScope is still very well supported, it is no longer necessary for most users of EF6.

While Database.BeginTransaction() is used only for database related operations transaction, System.Transactions.TransactionScope, in addition to that, makes it possible for 'plain C# code' to also be transactional.

Hence, use Database.BeginTransaction() where ever doing only db related operations in a transaction in EF6 otherwise use System.Transactions.TransactionScope for mixing db operations and C# code together in a transaction.

For those who still prefer the TransactionScope approach, it is recommended they checkout its limitations, especially in cloud scenarios (cloud scenarios do not support distributed transactions).

Further information can be found here

OTHER TIPS

The accepted and popular answer is misleading. Both Database.BeginTransaction() and TransactionScope are mainly for DB operations.

TransactionScope also extends transaction support beyond ADO.NET to MSMQ and Microsoft Distributed Transactions, but it doesn't support 'plain C# code' out of the box like mentioned in the other answer.

The main differences between Database.BeginTransaction() and TransactionScope:

Style

  • With TransactionScope the transaction is set implicitly by wrapping all transactional actions with a starting using scope = new TransactionScope and calling scope.Complete(); to commit. The BEGIN TRANSACTION command is not sent to SQL on the new TransactionScope but only when the code 'decides' a transaction should be open (usually it's deferred to when the first DB related code line run, like when a query to the DB is actually performed). The COMMIT not is sent to sql when reaching scope.Complete(); rather only when the using block ends and dispose is called - the transaction commands are implict.
  • With Database.BeginTransaction() the transaction is set explicitly - BEGIN TRANSACTION command is sent to DB exactly when the code runs the Database.BeginTransaction() line

TransactionScope offer broader options, BeginTransaction has a simpler API

  • TransactionScope allows to customize the transaction timeout, support nested transactions with various TransactionScopeOption support.

  • TransactionScope supports both distributed transactions (where multiple DB involved in a single transaction) and non-distributed transactions.

  • Database.BeginTransaction only supports non-distributed transactions (a local transaction where all actions are done within a single DB).

  • TransactionScope default isolation level is SERIALIZABLE while Database.BeginTransaction will use isolation level set on DB as default.

MSDN do state that with the new Database.BeginTransaction() and Database.UseTransaction() APIs, the TransactionScope approach is no longer necessary for most users.

Async Support

  • TransactionScope is implemented by connecting the transaction to current thread ([ThreadStatic] attribute), while BeginTransaction is achieved by connecting the transaction to a dbContext instance.

  • For async support, the AsyncFlow enabled flag should should be passed - new TransactionScope(TransactionScopeAsyncFlowOption.Enabled); It is needed for cases when await is used after opening the transaction (e.g. await _myReop.SaveItemAsync(item);).

Even when TransactionScopeAsyncFlowOption is enabled the TransactionScope would still be limited to the thread that created it (or sql commands performed from any child threads that were created from the parent thread that created the TransactionScope)

Advantages and disadvantages of TransactionScope:

Disadvantages of TransactionScope:

  • Requires .NET 4.5.1 or greater to work with asynchronous methods.
  • It cannot be used in cloud scenarios unless you are sure you have one and only one connection (cloud scenarios do not support distributed transactions).
  • It cannot be combined with the Database.UseTransaction() approach of the previous sections.
  • It will throw exceptions if you issue any DDL and have not enabled distributed transactions through the MSDTC Service or when used with .NET Core

Advantages of TransactionScope:

  • It will automatically upgrade a local transaction to a distributed transaction if you make more than one connection to a given database or combine a connection to one database with a connection to a different database within the same transaction (note: you must have the MSDTC service configured to allow distributed transactions for this to work).
  • Ease of coding. If you prefer the transaction to be ambient and dealt with implicitly in the background rather than explicitly under you control then the TransactionScope approach may suit you better.

Based on this MSDN article.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top