TransactionScope 不回滚事务
这是我的事务范围源代码的当前架构。 第三个插入抛出 .NET 异常(不是 SQL 异常),并且它不会回滚前两个插入语句。 我做错了什么?
编辑:我从 insert2 和 insert3 中删除了 try/catch。 我还从 insert1 try/catch 中删除了异常处理实用程序,并放置了“throw ex”。 它仍然不会回滚事务。
编辑2:我在Insert3方法上添加了try/catch,并在catch语句中添加了“throw”。 它仍然不会回滚事务。
更新:根据我收到的反馈,“SqlHelper”类使用 SqlConnection 对象建立与数据库的连接,然后创建一个 SqlCommand 对象,将 CommandType 属性设置为“StoredProcedure”并调用SqlCommand 的 ExecuteNonQuery 方法。
我也没有将 Transaction Binding=Explicit Unbind 添加到当前连接字符串。 我会在下次测试时添加这一点。
public void InsertStuff()
{
try
{
using(TransactionScope ts = new TransactionScope())
{
//perform insert 1
using(SqlHelper sh = new SqlHelper())
{
SqlParameter[] sp = { /* create parameters for first insert */ };
sh.Insert("MyInsert1", sp);
}
//perform insert 2
this.Insert2();
//perform insert 3 - breaks here!!!!!
this.Insert3();
ts.Complete();
}
}
catch(Exception ex)
{
throw ex;
}
}
public void Insert2()
{
//perform insert 2
using(SqlHelper sh = new SqlHelper())
{
SqlParameter[] sp = { /* create parameters for second insert */ };
sh.Insert("MyInsert2", sp);
}
}
public void Insert3()
{
//perform insert 3
using(SqlHelper sh = new SqlHelper())
{
SqlParameter[] sp = { /*create parameters for third insert */ };
sh.Insert("MyInsert3", sp);
}
}
Here is the current architecture of my transaction scope source code. The third insert throws an .NET exception (Not a SQL Exception) and it is not rolling back the two previous insert statements. What I am doing wrong?
EDIT: I removed the try/catch from insert2 and insert3. I also removed the exception handling utility from the insert1 try/catch and put "throw ex". It still does not rollback the transaction.
EDIT 2: I added the try/catch back on the Insert3 method and just put a "throw" in the catch statement. It still does not rollback the transaction.
UPDATE:Based on the feedback I received, the "SqlHelper" class is using the SqlConnection object to establish a connection to the database, then creates a SqlCommand object, set the CommandType property to "StoredProcedure" and calls the ExecuteNonQuery method of the SqlCommand.
I also did not add Transaction Binding=Explicit Unbind to the current connection string. I will add that during my next test.
public void InsertStuff()
{
try
{
using(TransactionScope ts = new TransactionScope())
{
//perform insert 1
using(SqlHelper sh = new SqlHelper())
{
SqlParameter[] sp = { /* create parameters for first insert */ };
sh.Insert("MyInsert1", sp);
}
//perform insert 2
this.Insert2();
//perform insert 3 - breaks here!!!!!
this.Insert3();
ts.Complete();
}
}
catch(Exception ex)
{
throw ex;
}
}
public void Insert2()
{
//perform insert 2
using(SqlHelper sh = new SqlHelper())
{
SqlParameter[] sp = { /* create parameters for second insert */ };
sh.Insert("MyInsert2", sp);
}
}
public void Insert3()
{
//perform insert 3
using(SqlHelper sh = new SqlHelper())
{
SqlParameter[] sp = { /*create parameters for third insert */ };
sh.Insert("MyInsert3", sp);
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
我也遇到了类似的问题。 出现问题是因为我在 SqlCommands 中使用的 SqlConnection 在创建 TransactionScope 之前就已打开,因此它从未作为事务列入 TransactionScope 中。
SqlHelper 类是否可能重用在您进入 TransactionScope 块之前打开的 SqlConnection 实例?
I have also run into a similar issue. My problem occurred because the SqlConnection I used in my SqlCommands was already open before the TransactionScope was created, so it never got enlisted in the TransactionScope as a transaction.
Is it possible that the SqlHelper class is reusing an instance of SqlConnection that is open before you enter your TransactionScope block?
看起来您正在捕获 Insert3() 中的异常,因此您的代码在调用后继续。 如果您希望它回滚,您需要让异常冒泡到主例程中的 try/catch 块,以便永远不会调用 ts.Complete() 语句。
It looks like you are catching the exception in Insert3() so your code continues after the call. If you want it to rollback you'll need to let the exception bubble up to the try/catch block in the main routine so that the ts.Complete() statement never gets called.
仅当退出 using 且未调用 ts.complete 时,才会发生隐式回滚。 因为您正在 Insert3() 中处理异常,所以该异常永远不会导致 using 语句退出。
要么重新抛出异常,要么通知调用者需要回滚(将 Insert3() 的签名更改为 bool Insert3()?)
An implicit rollback will only occur if the using is exited without calling ts.complete. Because you are handling the exception in Insert3() the exception never causes an the using statement to exit.
Either rethrow the exception or notify the caller that a rollback is needed (make change the signature of Insert3() to bool Insert3()?)
(基于不吞咽异常的编辑版本)
操作需要多长时间? 如果其中任何一个运行时间很长,则事务绑定
bug功能已经困扰您 - 即连接已断开。 尝试将Transaction Binding=Explicit Unbind
添加到连接字符串。(based on the edited version that doesn't swallow exceptions)
How long do the operations take? If any of them are very long running, it is possible that the Transaction Binding
bugfeature has bitten you - i.e. the connection has become detached. Try addingTransaction Binding=Explicit Unbind
to the connection string.我没有看到您的帮助程序类,但如果您不调用完整语句,即使您从 .NET 代码中收到错误,事务范围也会回滚。 我给你复制了一个例子。 您可能在调试时做错了什么。 此示例在 .net 代码中存在错误,并且与您的类似的 catch 块。
如果你想调试你的事务,你可以使用这个脚本来查看锁和等待状态等。
在调用异常方法之前,你将看到两个方法调用的一个SPID。
默认隔离级别是可序列化的。您可以在此处阅读有关锁和事务的更多信息
I dont see your helper class, but transaction scope rollsback if you don't call complete statement even if you get error from .NET code. I copied one example for you. You may be doing something wrong in debugging. This example has error in .net code and similar catch block as yours.
If you want to debug your transactions, you can use this script to see locks and waiting status etc.
You will see one SPID for two method calls before calling exception method.
Default isolation level is serializable.You can read more about locks and transactions here
当我在
TransactionScope
中调用 WCF 服务操作时,我遇到了类似的问题。我注意到由于服务接口中的“TransactionFlow”属性,不允许交易流。 因此,WCF 服务操作没有使用外部事务范围所使用的事务。 将其更改为允许交易流程,如下所示解决了我的问题。
到
I ran into a similar issue when I had a call to a WCF service operation in
TransactionScope
.I noticed transaction flow was not allowed due to the 'TransactionFlow' attribute in the service interface. Therefore, the WCF service operation was not using the transaction used by the outer transaction scope. Changing it to allow transaction flow as shown below fixed my problem.
to