2010-01-04 98 views
1

我有一个使用了大量SqlTranaction调用现有的应用程序。该应用程序的构建方式,我们得到了一堆代码,看起来有点像这样(为简便起见错误处理等去掉):我应该如何将SqlTransaction遗留代码与TranactionScope集成?

Using transaction As SqlTransaction = Database.CreateSqlTransaction() 
    If Not Me.FitnessSession.FitnessTestSessionID.HasValue Then 
     Me.FitnessSession.Insert(transaction) 
    Else 
     Me.FitnessSession.Update(transaction) 
    End If 
    SaveTestScores(transaction) 

    Database.CommitTransaction(transaction) 'This essentially just calls transaction.Commit() 

End Using 

我们在开沟出手卷DAL和移动到LINQ的过程到SQL,但这将是增量式的,因为我们没有预算来简单地丢弃所有我们的遗留代码。因此,我们将在我们需要使用我们的旧代码和Linq到SQL代码的所有领域都处于同一事务中。我相信这可以这样做:

Using scope As New TransactionScope() 
Using transaction As SqlTransaction = Database.CreateSqlTransaction() 
    If Not Me.FitnessSession.FitnessTestSessionID.HasValue Then 
     Me.FitnessSession.Insert(transaction) 
    Else 
     Me.FitnessSession.Update(transaction) 
    End If 
    SaveTestScores(transaction) 

    Database.CommitTransaction(transaction) 

End Using 
End Using 

什么我就被其承诺称不清楚,我必须打电话scope.Complete()Database.CommitTransaction(transaction)?或者还有其他一些选项将两段代码链接在一起?

跟进质询,
感谢@编程英雄那是真正有用的,什么我现在不能确定的是,我的时候应该关闭SQL连接?该DAL方法中的代码使一个检查,看是否已经通过了一项交易,如果有,那么它使用对事务的连接并没有关闭连接,一旦完成后,如果没有交易过那么新连接打开并关闭操作。如果我关闭了TransactionScope中的SqlConnection,这是否会导致环境事务出现问题?我问,因为如果关闭具有SqlTransaction对象的SqlConnection,事务将回滚。

回答

2

命名空间System.Transactions的用途是允许您在整个应用程序中控制来自单个模型的事务。使用System.Transactions提供的交易模式时,应避免使用任何明确的交易,如SqlTransaction;在明确的交易中混合会使您的生活变得相当困难,因为您必须手动管理这两种模型。

对你的好消息:当您使用ADO.NET组件您获得环境事务的内置支持。这意味着你可以删除所有引用SqlTransaction和传递交易的情况下物体周围,为System.Transactions模型会照顾一切的为您服务。

的环境事务模型可以作为一个包装,并协调其他各种具体事务。 ADO.NET组件知道要查找环境事务并在内部设置自己的特定事务(如SqlTransaction)。该System.Transactions组件预警所有的士兵交易的“全局”事务TransactionScope块管理的状态。

如果您的代码在TransactionScope区块内执行,则会有一个环境事务可供事务感知组件参与。对于您的数据访问代码,所有交互都将发生在同一事务中,而不管是否它们是您自己的DAL或Linq to SQL组件的一部分。所有你需要知道的是,只要有人在场,他们就会参加环境交易。

要成功完成TransactionScope块,只需在工作结束时在本地实例上调用TransactionScope.Complete()即可。为每一个你在其中工作的块做这件事,当最顶级块完成时,物理事务将落实。

没有必要调用任何其他交易特定的代码,因为他们应该都(幕后)与您的System.Transaction协调。

有了这一切记住,你的代码可以是这样的:

Using scope As New TransactionScope() 

    If Not Me.FitnessSession.FitnessTestSessionID.HasValue Then 
     Me.FitnessSession.Insert() 
    Else 
     Me.FitnessSession.Update() 
    End If 

    SaveTestScores() 

    scope.Complete() 

End Using 

特定数据库事务的所有引用都消失了。所有操作都将在TransactionScope提供的环境交易中发生。在此块中,您还可以使用SqlCommand直接调用,或者使用Linq-to-SQL对象而不指定任何显式事务,并且它们将参与环境事务。

+2

我同意。一个警告 - 'TransactionScope'将升级到一个分布式事务(这是一个用于部署的PITA),除非所有数据访问代码共享一个打开的连接对象。 – 2010-01-04 17:45:27