我正在使用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)应用于在该上下文中生成的查询吗?
答案 0 :(得分:12)
简答:否
仅定义TransactionScope并未定义将在事务中调用任何读取或写入。
要在事务中运行某些内容,您仍然需要打开并提交事务!
TransactionOptions
和Timeout
的TransactionScope的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
-
请纠正我,如果这些信息可能有误,我只是自己想出来这样可能会有一些失败的原因;)
答案 1 :(得分: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