多个TransactionScope存在的问题

6

我想创建一个事务,在子事务中写入一些数据,读取数据,然后回滚事务。

using(var transaction = new TransactionScope()) 
{
     using(var transaction = new TransactionScope()) 
     {
          // save data via LINQ / DataContext
          transaction.Complete();
     }
     // Get back for assertions
     var tempItem = // read data via LINQ / DataContext THROWS EXCEPTION
} 

在阅读过程中,我遇到了"System.Transactions.TransactionException : The operation is not valid for the state of the transaction."的错误提示。

我应该如何设置事务属性以避免这种情况发生呢?


你在使用哪个数据库? - TheVillageIdiot
在什么情况下,SQLConnection会自动注册到环境事务中? - Joe
2个回答

9
这个异常如果没有完整的堆栈跟踪是无法调试的。它的意义取决于上下文。通常情况下,这意味着您在事务内做了一些不应该做的事情,但是如果没有看到数据库调用或堆栈跟踪,任何人都只能猜测。我知道的一些常见原因(这绝不是全面的)包括:
  1. 在嵌套的 TransactionScope 中访问多个数据源(即不同的连接字符串)。这会导致升级为分布式事务,如果您没有运行 DTC,则会失败。答案通常不是启用 DTC,而是清理您的事务或使用新的 TransactionScope(TransactionOptions.RequiresNew) 包装其他数据访问。
  2. TransactionScope 内未处理的异常。
  3. 任何违反隔离级别的操作,例如尝试读取刚插入/更新的行。
  4. SQL 死锁;在某些情况下,事务甚至可以自己死锁,但如果适用于 #1,则将其他操作隔离到新事务中可能会导致死锁,如果您不小心。
  5. 事务超时。
  6. 来自数据库的任何其他错误。
我肯定不知道每个可能的原因,但如果您发布完整的堆栈跟踪和代码中实际的数据库调用,我会查看并让您知道是否有任何问题。

Andy,感谢您的回答。关于第3个问题:“违反隔离级别的任何操作”,以下操作是否会违反隔离级别?DECLARE (atSmbol)someCount INT; UPDATE dbo.Something SET (atSmbol)someCount = [SomeCount] = [SomeCount]+ 1 WHERE ID = 123在我的用法中,(atSmbol)someCount是一个输出参数。如果是这样,这不是违反了隔离级别吗?DECLARE (atSmbol)someCount INT; UPDATE dbo.Something SET [SomeCount] = (atSmbol)someCount = [SomeCount]+ 1 WHERE ID = 123请注意,当我使用@符号时,它会认为我正在尝试标记某人以进行通知。 - Wes

4

是的,嵌套的。但是你为什么要链接MSDN? - boj
也许因为链接的文章解释了为什么会出现那个异常? - Josh E
@boj:因为它有一个使用示例,配有良好的注释,解释了何时发生什么。 - hollystyles

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接