如果出现错误,使用using语句会回滚数据库事务吗?

87

我在使用一个 IDbTransaction 的 using 语句块,但我不确定如果在 using 语句块内抛出异常时它是否会被回滚。我知道 using 语句块将强制调用 Dispose() 方法……但是有人知道 Rollback() 方法是否也是这样的吗?

更新:另外,我是否需要显式调用 Commit() 方法,就像下面的代码一样,还是 using 语句块会自动处理呢?

我的代码看起来像这样:

using Microsoft.Practices.EnterpriseLibrary.Data;

...

using(IDbConnection connection = DatabaseInstance.CreateConnection())
{
    connection.Open();

    using(IDbTransaction transaction = connection.BeginTransaction())
    {
       //Attempt to do stuff in the database
       //potentially throw an exception
       transaction.Commit();
    }
}

3
嗨,我来解释一下“commit”这个案例。它当然是强制性的,因为using(){}只是调用Dispose()方法。如果Commit也是自动的,Transaction.Dispose类可能无法知道它是应该提交还是处理 :) - Manitra Andriamitondra
请参见 https://dev59.com/-Gw15IYBdhLWcg3wv-Xa - nawfal
3个回答

107

对于事务类的Dispose方法会执行回滚操作,而Oracle的类则不会。因此从事务的角度来看,它是依赖于实现的。

另一方面,对于连接对象,using语句要么关闭与数据库的连接,要么将连接重置并返回到池中。无论哪种情况,未完成的事务都应该被回滚。这就是为什么异常不会留下未完成的事务。

另外,是的,您应该显式调用Commit()


1
这是可以的,我甚至曾经通过显式抛出异常来测试过。 - Pawel Krakowiak
1
这很棒,但如果您将其用于跨数据库兼容性,它是否适用于IDbTransaction的其他实现? - Matt Hamilton
4
@mezoid:Commit永远不会自动发生。 @matt:根据设计,它们应该自动发生。 - Sedat Kapanoglu
2
@MattHamilton,就像ssg所说的那样。我检查了MySQL的.NET连接器源代码,他们也像上面展示的一样做了。RollbackDispose中被调用! :) - nawfal
1
如果您正在使用 System.Data.OracleConnection,它不会在释放时回滚。或者至少对我们来说是这样的。 - Medinoc
显示剩余2条评论

19

你必须调用commit方法。使用using语句不能自动提交。


8
是的,在退出时使用会调用Dispose,它将调用Rollback而不是Commit。 - awe

6
我认为如果存在这样的异常,即Commit()从未被调用,则事务将自动回滚。

是的,那是我的理解。一个事务会一直存在,直到调用提交或连接结束。在这一点上,如果连接关闭,则实际上会将事务日志更新为更改内容或回滚(你知道你永远不会从关闭的连接中获得提交;). - Mike

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