65.9K
CodeProject 正在变化。 阅读更多。
Home

.NET TransactionScope 及其默认事务隔离级别问题

starIconstarIconstarIconstarIconstarIcon

5.00/5 (5投票s)

2013年2月1日

CPOL

1分钟阅读

viewsIcon

52519

.NET TransactionScope 及其默认事务隔离级别问题。

介绍 

我们经常使用 .NET Framework 的 TransactionScope 对象来管理/处理数据库事务。通常,我们会像以下这样创建一个 TransactionScope 对象实例

var scope = new
TransactionScope(TransactionScopeOption.Required, new TimeSpan(0, 0, 1, 0)) 

或者

var scope = new TransactionScope() 

或者使用其他重载的构造函数。一切正常。但故事从收到超时异常消息时开始。

详情 

实际上这是一个死锁异常。因此,任何人都会认为这是由于并发用户访问相同的资源(数据库行)引起的,这可能是一个非常罕见的情况,并忽略它。但不幸的是,它一次又一次地出现,你无法忽视它。我开始研究以了解死锁一次又一次发生的原因。为什么会发生?首先,我开始调查 TransactionScope 对象。我试图找出该组件是否存在任何问题。最终我得到了答案。调查结果是 TransactionScope 对象的默认隔离级别是 Serializable(可串行化)。这是导致在某些情况下引发此类死锁异常的罪魁祸首。如果我们需要解决这个问题,我们应该使用其他隔离级别,例如 ReadCommitted(已提交读取)。正如我们所知,SQL Server 使用 ReadCommitted 作为默认隔离级别。建议在一般情况下使用它。

如何修复

在业务层中创建一个工厂方法(考虑到事务将由业务层管理)。

工厂方法体如下

public static TransactionScope CreateTransactionScope()
 { 
    var transactionOptions = new TransactionOptions 
    { 
        IsolationLevel = IsolationLevel.ReadCommitted,
        Timeout = net TimeSpan(0,0,0,0,10,0) //assume 10 min is the timeout time
    }; 
    return new TransactionScope(TransactionScopeOption.Required, transactionOptions); 
} 

工厂方法的使用

与像以下这样使用默认构造函数创建 TransactionScope 对象不同

using (var scope = new 
TransactionScope(TransactionScopeOption.Required, new TimeSpan(0, 0, 1, 0)))

我们可以借助工厂方法创建该对象,这将实现我们的目的。

using (var scope =  CreateTransactionScope() )   { 
    saveProjectEntity();
    scope.Complete(); 
} 
.NET TransactionScope 及其默认事务隔离级别问题 - CodeProject - 代码之家
© . All rights reserved.