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





5.00/5 (5投票s)
.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();
}