在我们的项目中,我们使用TransactionScope来确保我们的数据访问层在事务中执行它的操作。 我们的目标是不要求我们的terminal用户的机器上启用MSDTC服务。 麻烦的是,在我们的一半开发人员机器上,我们可以禁用MSDTC来运行。 另一半必须启用它或他们得到“MSDTC on [服务器]不可用”错误消息。 这真让我挠头,让我认真考虑回滚到基于ADO.NET事务对象的基于TransactionScope的解决scheme。 这看起来很疯狂 – 对我们开发人员的一半工作(而不是升级)相同的代码在其他开发人员的升级。 我希望有一个更好的答案跟踪为什么交易升级到DTC,但不幸的是它不。 下面是一些会导致麻烦的代码示例,在尝试升级的机器上,尝试在第二个连接上升级。打开()(是的,当时没有其他连接打开)。 using (TransactionScope transactionScope = new TransactionScope() { using (SqlConnection connection = new SqlConnection(_ConStr)) { using (SqlCommand command = connection.CreateCommand()) { // prep the command connection.Open(); using (SqlDataReader reader = command.ExecuteReader()) { // use the reader connection.Close(); } } } // Do other stuff […]
我对以下模式的副作用和潜在问题感兴趣: CREATE PROCEDURE [Name] AS BEGIN BEGIN TRANSACTION BEGIN TRY […Perform work, call nested procedures…] END TRY BEGIN CATCH ROLLBACK TRANSACTION RAISERROR [rethrow caught error using @ErrorNumber, @ErrorMessage, etc] END CATCH END 据我所知,这种模式在使用单个过程时是合理的 – 过程将完成所有的语句而没有错误,或者它将回滚所有的操作并报告错误。 但是,当一个存储过程调用另一个存储过程来完成某个子单元的工作时(我们理解小过程有时自己会被调用),所以我看到一个与回滚有关的问题 – 一个信息性消息(级别16)发出说明The ROLLBACK TRANSACTION request has no corresponding BEGIN TRANSACTION. 。 我假设这是因为子过程中的回滚总是回滚最外层的事务,而不仅仅是在子过程中启动的事务。 我希望整个事情回滚和中止,如果有任何错误发生(和错误报告给客户端作为SQL错误),我只是不确定所有来自外层尝试回滚事务的副作用已经回滚了。 在每个TRY CATCH层执行回滚之前,可能需要检查@@TRANCOUNT ? 最后是客户端(Linq2SQL),它有自己的事务层: try { […]