I've been reading a document from Microsoft's patterns & practices group (Data Access for Highly-Scalable Solutions: Using SQL, NoSQL, and Polyglot Persistence).
In Chapter 3, in the section "Retrieving Data from the SQL Server Database", the authors discuss using Entity Framework to load entities from a database. Here's a bit of their sample code:
using (var context = new PersonContext()) { Person person = null; using (var transactionScope = this.GetTransactionScope()) { person = context.Persons .Include(p => p.Addresses) .Include(p => p.CreditCards) .Include(p => p.EmailAddresses) .Include(p => p.Password) .SingleOrDefault(p => p.BusinessEntityId == personId); transactionScope.Complete(); } // etc... } Note the use of a custom transaction scope via the GetTransactionScope method, implemented in their base context class like so:
public abstract class BaseRepository { private static TransactionOptions transactionOptions = new TransactionOptions() { IsolationLevel = IsolationLevel.ReadCommitted }; protected virtual TransactionScope GetTransactionScope() { return new TransactionScope(TransactionScopeOption.Required, transactionOptions); } } Working with Transactions (EF6 Onwards) on MSDN states:
In all versions of Entity Framework, whenever you execute SaveChanges() to insert, update or delete on the database the framework will wrap that operation in a transaction [...] the isolation level of the transaction is whatever isolation level the database provider considers its default setting. By default, for instance, on SQL Server this is READ COMMITTED. Entity Framework does not wrap queries in a transaction. This default functionality is suitable for a lot of users
The bold emphasis is mine.
My question: is the use of a TransactionScope as shown above overkill, particularly for data reads, when using Entity Framework?
(I realised after posting that the answer to this question might be somewhat opinion-based, sorry about that.)
isolationLevel, this code is overkill if the transaction contains only read operation. But if theisolationLevelisReadUncommited, this code will allow you to read dirty row (not commited yet).