我有一个使用大量SqlTranaction调用的现有应用程序。构建应用程序的方式我们得到了一堆看起来有点像这样的代码(为简洁起见,删除了错误处理等):
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 to SQL,但这将是渐进的,因为我们没有预算来简单地抛弃我们所有的遗留代码。因此,我们将需要在同一事务中使用旧代码和Linq to 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)
?或者是否有其他选项将两位代码链接在一起?
跟进问题
感谢@ programming-hero,这真的很有帮助,我现在不确定的是,什么时候应该关闭sql连接? DAL方法中的代码检查它是否已通过事务,如果有,则它使用该事务上的连接,并且一旦完成就不关闭连接,如果没有传递任何事务则为新连接打开和关闭以进行操作。如果我在TransactionScope中关闭SqlConnection,这会导致环境事务的问题吗?我问,因为如果我关闭一个具有SqlTransaction对象的SqlConnection,事务就会被回滚。
答案 0 :(得分: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对象而不指定任何显式事务,并且它们将参与环境事务。