【问题标题】:TransactionScopeOption - Required or RequiresNewTransactionScopeOption - 必需或 RequiresNew
【发布时间】:2011-06-05 11:32:37
【问题描述】:

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

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

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

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

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

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 的正确值(RequiresNewRequired)。

感谢您的回复。

【问题讨论】:

    标签: .net transactions constructor transactionscope


    【解决方案1】:

    如果另一个方法调用ProcessRequest 在另一个事务中,这取决于您希望发生什么:

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

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

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

    【讨论】:

    • 就我而言,ProcessRequest 方法本身永远不会参与另一个事务。我只是想确保在请求执行后:“数据库查询以验证数量是否仍然大于零”,然后执行:“数据库查询以请求和减少数量”数量尚未达到零,因为另一个请求,执行相同的方法 ProcessRequest。所以,我猜默认值:TransactionScope.Required 对我来说是正确的值。
    • 肯定 - 否则,您会(无意中)暗示 ProcessRequest 有一些特殊之处需要它使用自己的事务。
    【解决方案2】:

    我了解您的方法不会在另一个事务中被调用。但如果它会,这里是你如何选择TransactionScopeOption

    如果 ProcessRequest 写入数据库的内容不能被任何调用者推翻,请使用RequiresNew,它会启动一个与调用者(如果有)创建的事务并行的新事务,并且调用者不以任何方式管理新事务。 最好认为事务不能嵌套,要么使用现有事务,要么创建一个新事务。 事务不嵌套!

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

    您可能会发现下表很有用。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-02-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-07-22
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多