我正在测试使用TransactionScope与设置隔离级别为ReadUncommitted选项来执行特定查询。但是,我发现由于隔离级别在连接上设置,当连接被重用于其他查询时,隔离级别仍然是ReadUncommitted,而不是重置为默认的ReadCommitted。
根据许多建议,我将新的NoLock方法作为扩展进行了抽象,如下所示:
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();
}
}
}
我想验证在事务范围内和事务范围外运行的各种查询的隔离级别。为此,我使用查询的上下文开始执行以下查询:
db.ExecuteQuery<int>("select cast(transaction_isolation_level as int) from sys.dm_exec_sessions where session_id = @@SPID").FirstOrDefault();
在执行NoLock扩展方法之前,运行上述内容会返回隔离级别为2。在运行NoLock扩展方法并检查事务范围外的查询隔离级别后,返回1。
这是否意味着当使用TransactionScope更改隔离级别时,受影响的连接(如果被重用于其他查询和数据上下文)仍将使用ReadUncommitted隔离级别?这不是在所有查询之后影响所有查询的情况下使用事务临时更改隔离级别的目的吗?
READ UNCOMMITTED
可以返回脏读。 这些可能包括从技术上讲从未属于数据库的记录。 来源 - MSDN。 更多内容请参见这篇博客文章。 - David Rushton