将TransactionScope与read uncommitted一起使用 - 是否必须在SQL中使用(nolock)?

Mez*_*Mez 10 nhibernate transactions fluent-nhibernate sql-server-2008 c#-4.0

我正在使用FluentNHibernate,我有一个记录列表,映射到SQL Server 2008视图.脏的读取对我来说没关系,不锁定表是一个优先事项.

视图中的SQL查询,没有任何with(nolock),但是,我使用以下方法...

using (var txScope = new TransactionScope(TransactionScopeOption.Suppress, new TransactionOptions() { IsolationLevel = System.Transactions.IsolationLevel.ReadUncommitted }))
{
   ... The reading of records from the view is done here, through Fluent NHibernate...
}

是否将应用程序层的隔离级别设置为未提交读取,将(nolock)应用于在该上下文中生成的查询?

Mic*_*haC 12

简答:不

答案很长:

仅定义TransactionScope并未定义将在事务中调用任何读取或写入.

要在事务中运行某些内容,您仍然必须打开并提交事务!

TransactionOptions该TransactionScope的为TimeoutIsolationLevel刚刚定义的默认设置为不明确地设置这些选项的范围内创建的任何交易.实际上,TransactionScope确实创建了一个事务,但如果没有打开新事务,它将不会处于活动状态.在内部,这将做一些复杂的事情,克隆事务等...所以让我们忽略这个......

如果没有事务,您无法定义隔离级别,将运行任何select语句,IsolationLevel.ReadCommitted因为这是SQL Server的默认值.

您还可以查询session.Transaction.IsActive以查看会话当前是否处于活动状态!

让我们看看下面的代码,我提出一些意见,使其更清晰一点

using (var scope = new TransactionScope(TransactionScopeOption.Required,
                    new TransactionOptions()
                    {
                        IsolationLevel = IsolationLevel.ReadUncommitted
                    }))
{

    using (var session = sessionFactory.OpenSession())
    {
        // outside any transaction...
        var x = session.Transaction.IsActive; // false;

        // read will be done with SQL Server default (ReadCommited)
        var pp = session.Query<Page>().Where(p => p.Photos.Count() > 1).ToList();

        using (var transaction = session.BeginTransaction())
        {
            // will use ReadUncommitted according to the scope
            var y = session.Transaction.IsActive; // true;

            var p1 = session.Get<Page>(1);

            transaction.Commit();
        }
        using (var transaction = session.BeginTransaction(System.Data.IsolationLevel.ReadCommitted))
        {
            // will use ReadCommitted according to the transaction initialization
            var y = session.Transaction.IsActive; // true;

            var p1 = session.Get<Page>(1);

            transaction.Commit();
        }

        scope.Complete();
    }
}
Run Code Online (Sandbox Code Playgroud)

您还可以使用SQL Server Profiler观察SQL Server如何对这些设置做出反应.

只需创建一个新的Trace并注意Audit Login事件,事件的文本将包含隔离级别,您可以看到它实际上Audit Login每次创建事务时都会执行,例如

 set transaction isolation level read uncommitted
Run Code Online (Sandbox Code Playgroud)

-

如果任何这些信息可能有误,请纠正我,我只是自己想出来,所以可能会有一些失败的可能性;)