11

我正在使用 FluentNHibernate,并且我有一个记录列表,映射到 SQL Server 2008 视图。脏读对我来说没问题,不锁定表是一个优先事项。

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

使用 (var txScope = new TransactionScope(TransactionScopeOption.Suppress, new TransactionOptions() { IsolationLevel = System.Transactions.IsolationLevel.ReadUncommitted }))
{
   ... 通过 Fluent NHibernate 从视图中读取记录在这里完成...
}

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

4

2 回答 2

14

简短的回答:没有

长答案:

仅仅定义 TransactionScope 并没有定义在事务中将调用任何读取或写入。

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

TransactionOptionsTransactionScope 的,Timeout只为在范围内创建的任何事务IsolationLevel定义默认值,而没有显式设置这些选项。实际上,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();
    }
}

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

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

 set transaction isolation level read uncommitted

--

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

于 2013-09-30T17:26:04.467 回答
0

我不知道为什么,但 TransactionScope 代码对我不起作用。

我使用了这段代码。在下方开始一个新会话可确保您还没有现有事务。(当然还有其他方法)

        using (var session = _session.SessionFactory.OpenSession())
        using (var txn = session.BeginTransaction(IsolationLevel.ReadUncommitted))
        {
            // bunch of select statements.
        }

在 NHibernate Profiler 中,我可以看到:

begin transaction with isolation level ReadUncommitted
于 2015-05-15T14:14:26.447 回答