I'm testing out using TransactionScope with options to set the isolation level to ReadUncommitted to execute specific queries with as such. What I'm seeing, however, is that because the isolation level is set on the connection, when the connection is reused for other queries the isolation level is still ReadUncommitted instead of resetting to the default ReadCommitted.
Per many suggestions, I abstracted new NoLock methods as extensions as follows:
public static class QueryableExtensions
{
static TransactionScope CreateNoLockTransaction()
{
return new TransactionScope(TransactionScopeOption.Required, new TransactionOptions
{
IsolationLevel = IsolationLevel.ReadUncommitted
});
}
public static T[] ToNoLockArray<T>(this IEnumerable<T> query)
{
using (var ts = CreateNoLockTransaction())
{
return query.ToArray();
}
}
public static List<T> ToNoLockList<T>(this IEnumerable<T> query)
{
using (var ts = CreateNoLockTransaction())
{
return query.ToList();
}
}
public static int NoLockCount<T>(this IEnumerable<T> query)
{
using (var ts = CreateNoLockTransaction())
{
return query.Count();
}
}
}
I then wanted to verify the isolation level on the various queries I run both within the transaction scope and without. To do that I started executing the following query using the context of the query:
db.ExecuteQuery<int>("select cast(transaction_isolation_level as int) from sys.dm_exec_sessions where session_id = @@SPID").FirstOrDefault();
Running the above before executing the NoLock extension methods returns the isolation level as 2. After running the NoLock extension methods and checking the isolation level of queries outside the transaction scope then returns 1.
Does this mean that when changing the isolation level using TransactionScope the impacted connection, when reused for other queries and data contexts, continues to use the ReadUncommitted isolation level? Doesn't that defeat the purpose of using a transaction to temporarily change isolation level for a specific query since it impacts all queries thereafter?