我需要“ transactionScope.Complete();”吗?

时间:2018-12-06 18:21:08

标签: c# sql .net sql-server linq-to-sql

据我了解,使用SELECT tl.text FROM text_lines tl LEFT JOIN bak_lines bl ON tl.text = bl.text WHERE bl.text is null 的“正确”方法是始终在退出TransactionScope块之前调用transactionScope.Complete();。像这样:

using

但是,我已经看到代码没有它就可以工作,甚至the answer I've learnt to use it from都将其省略。所以我的问题是,是否必须使用它?

3 个答案:

答案 0 :(得分:7)

  

所以我的问题是,是否必须使用它?

为进行Complete交易而进行更新时必须使用

COMMIT。否则,事务管理器将发出ROLLBACK并撤消所做的更改。

对于像您的示例这样的只读事务,无论有没有Complete,我都认为没有实质性的区别。在两种情况下,事务管理器发出的COMMITROLLBACK具有释放事务持有的锁和资源的相同净效果。

尽管不是必须在只读事务中调用Complete,但它仍然是IMHO的最佳做法。考虑一下这个可怜的开发人员,他后来在不知不觉中丢失了Complete的情况下,无意中将数据修改代码添加到了您的事务块中。

答案 1 :(得分:3)

是的,您需要使用它,它是通过TransactionScope类上的Microsoft文档向编译器通知您已成功完成任务的方式:

  

当您的应用程序完成它希望在事务中执行的所有工作时,您应该只调用一次Complete方法,以通知该事务管理器可以接受提交事务。未能调用此方法将中止事务。

也用于Complete方法:

  

未能调用此方法将中止事务,因为事务管理器将其解释为系统故障或在事务范围内引发的异常。但是,您还应该注意,调用此方法不能保证事务的落实。这只是一种向交易经理通知您身份的方法。

答案 2 :(得分:0)

基本上using语句在C#编译器的编译时转换为该语句。

       TransactionScope transactionScope = new TransactionScope(TransactionScopeOption.Required, new TransactionOptions { IsolationLevel = IsolationLevel.ReadUncommitted })
        try
        {
           //your works
        }
        finally
        {
            if (transactionScope != null)
                ((IDisposable)transactionScope).Dispose();
        }

所以这就是C#的全部期望...。您只需要使用TransactionScope进行工作

如果TransactionScope对象最初创建了事务,则事务管理器提交事务的实际工作发生在using块中的最后一行代码之后。如果未创建事务,则每当Transaction对象的所有者调用Commit时,都会进行提交。那时,事务管理器将根据是否在TransactionScope对象上调用了Complete方法,来调用资源管理器并通知他们进行提交或回滚。

调用此方法不能保证事务将被提交。这只是一种向交易经理通知您身份的方法。调用Complete方法后,您将无法再使用Current属性访问环境事务,而尝试执行该操作将导致引发异常。

using语句确保即使发生异常,也将调用TransactionScope对象的Dispose方法。 Dispose方法标记事务作用域的结束。调用此方法后发生的异常可能不会影响事务。此方法还可以将环境事务还原到以前的状态。

如果范围创建了事务,则抛出TransactionAbortedException,并且事务中止。如果事务管理器无法达到Commit决策,则抛出TransactionInDoubtException。如果事务已提交,则不会引发异常。

希望这会为您清除