我目前对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 或必需)的正确价值。
感谢您的回复。
答案 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
,因为您不知道是否有任何被叫方偷偷创建了一个事务并将其回滚。