TransactionScopeOption - 必需或RequiresNew

时间:2011-01-07 19:05:06

标签: .net transactions constructor transactionscope

我目前对TransactionScope对象的构造函数感到困惑。

假设我网站的用户可以订购产品。在提交请求时,我会对剩余的当前数量进行验证,如果仍然大于零,我会执行请求。然后,最后我减少了剩下的当前数量。

整个过程都在一个事务中,使用.NET transactionScope。

在阅读了几篇关于.NET transactionScope对象的文章之后,我现在对TransactionScopeOption用于transactionScope构造函数的值感到有些困惑。

以下哪一项更适合上述情况:

public void ProcessRequest()  
 {  
     TransactionOptions transactionOptions = new TransactionOptions();  
     transactionOptions.IsolationLevel = IsolationLevel.Serializable;  
     using (TransactionScope currentScope = new TransactionScope(TransactionScopeOption.RequiresNew, transactionOptions)) {  
      // DB Query to verify if quantity is still greater than zero  
      // DB Query to request and decrement quantity 
      currentScope.Complete();
     }  
 }  

public void ProcessRequest()  
 {  
     TransactionOptions transactionOptions = new TransactionOptions();  
     transactionOptions.IsolationLevel = IsolationLevel.Serializable;  
     using (TransactionScope currentScope = new TransactionScope(TransactionScopeOption.Required, transactionOptions)) {  
      // DB Query to verify if quantity is still greater than zero  
      // DB Query to request and decrement quantity 
      currentScope.Complete();
     }  
 }  

请注意,上述内容仅仅是对我实际问题的过度简化。对于这种情况,我只想知道TransactionScopeOption( RequiresNew 必需)的正确价值。

感谢您的回复。

2 个答案:

答案 0 :(得分:16)

如果另一种方法在另一个交易中调用ProcessRequest ,这取决于您想要发生的事情:

public void SomeOtherMethod() {
    using (TransactionScope ts = new TrasansctionScope()) {
        // Another DB action
        ProcessRequest();
        // Yet another DB action
    }
}

如果您希望ProcessRequest使用SomeOtherMethod创建的交易,请使用TransactionScope.Required。这是默认设置(当你调用它时它仍会创建一个事务,而不会在调用堆栈中创建另一个事务范围)。

如果您希望它强制此方法始终使用自己的(新)事务,请使用TransactionScope,RequiresNew

答案 1 :(得分:7)

我知道您的方法不会在另一个交易中被调用。但万一会这样,你可以选择TransactionScopeOption

如果任何调用者都无法推翻ProcessRequest写入数据库的内容,请使用RequiresNew,这会启动与调用者创建的新事务 parallel (如果有),并且新的交易不是由呼叫者以任何方式管理的。 最好不要嵌套交易,无论是使用现有交易还是创建新交易。交易不是嵌套的!

如果可以推翻ProcessRequest写入数据库的内容,请使用Required。但是,此选项不透明;对ProcessRequest的调用者必须知道ProcessRequest可能会回滚,因为如果被调用者回滚环境事务,则调用者不能执行任何sql操作,否则异常"该操作对事务的状态无效。"将被抛出。在运行任何查询之前,最好始终检查System.Transactions.Transaction.Current.TransactionInformation.Status,因为您不知道是否有任何被叫方偷偷创建了一个事务并将其回滚。

您可能会发现下表很有用。 enter image description here