首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >TransactionScope会在某些机器上自动升级到MSDTC的吗?

TransactionScope会在某些机器上自动升级到MSDTC的吗?
EN

Stack Overflow用户
提问于 2018-02-26 05:10:03
回答 6查看 0关注 0票数 0

在我们的项目中,我们使用TransactionScope来确保我们的数据访问层在事务中执行它的操作。我们的目标是不要求我们的最终用户机器上启用MSDTC服务。

问题是,在我们一半的开发人员机器上,我们可以在禁用MSDTC的情况下运行。另一半必须启用它,否则他们将获得“MSDTC on服务器不可用“错误信息。

跟踪事务升级到dtc的原因

以下为示例代码,在试图升级的机器上,它尝试在第二个连接中升级.Open()(当时并没有打开其他连接)

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 here that may or may not involve enlisting 
   // in the ambient transaction

   using (SqlConnection connection = new SqlConnection(_ConStr)) {
      using (SqlCommand command = connection.CreateCommand()) {
         // prep the command
         connection.Open();  // Throws "MSDTC on [SERVER] is unavailable" on some...

         // gets here on only half of the developer machines.
      }
      connection.Close();
   }

   transactionScope.Complete();
}

以下是它工作机器的一些信息:

  • 开发1:Windows 7 x64 SQL 2008
  • 开发2:Windows 7 x86 SQL 2008
  • 开发3:Windows 7 x64SQL 2005SQL 2008

不针对开发人员:

  • 开发4:Windows 7 x64,SQL 2008SQL 2005
  • 开发5:WindowsVista x86,SQL 2005
  • 开发6:Windows XP X86,SQL 2005
  • My Home PC:WindowsVista家庭高级版,x86,SQL 2005

所有机器为了寻找问题都已经完全用Microsoft Update提供的所有软件进行了修补。

MSDN事务升级页面声明,以下条件将导致事务升级到DTC:

  1. 事务中至少登记了一个不支持单阶段通知的持久资源。
  2. 事务中至少有两个支持单阶段通知的持久资源。例如,使用单个连接注册并不会导致事务升级。但是,每当你打开到数据库的第二个连接导致数据库登记时,System.Transactions会检测到它是事务中的第二个持久资源,并将其升级为MSDTC事务。
  3. 调用将事务“编组”到不同应用程序域或不同进程的请求。例如,跨应用程序域边界的事务对象的序列化。事务对象是按值排列的,这意味着任何试图跨应用程序域边界(甚至在同一进程中)传递它的尝试都会导致事务对象的序列化。您可以通过调用远程方法来传递事务对象,该方法以事务作为参数,或者尝试访问远程事务服务组件。这将序列化事务对象并导致升级,就像在应用程序域中序列化事务一样。它正在被分发,而本地事务管理器已不再够用。

我重新调查了每个人的SQL Server版本 - “Dev 3”实际上有SQL2008,“Dev 4”实际上是SQL2005。 由于数据的这种变化,我已经确定找到了问题。 我们的SQL2008开发人员没有遇到这个问题,因为SQL2008包含SQL2005所没有的功能。

由于我们支持SQL 2005,所以不能像以前那样使用TransactionScope。如果我们想要使用TransactionScope,我们需要在周围传递一个SqlConnection对象...这在SqlConnection很难被传递的情况下是有问题的。它只是看起来像是全局-SqlConnection实例。

SQL 2008:

  • 允许在单个TransactionScope中进行多个连接(如上面的示例代码所示)。
  • 警告1:如果这些多个SqlConnections是嵌套的,也就是说,同时打开两个或多个SqlConnections,TransactionScope将立即升级到DTC。
  • 警告2:如果另一个SqlConnection打开到不同的“持久资源”(即:不同的SQL Server,),它会立即升级到DTC

SQL 2005:

  • 不允许单个TransactionScope中的多个连接。 当/打开第二个SqlConnection时,它会升级。

通过使用单个SqlConnection将SQL2005升级到DTC

using (TransactionScope transactionScope = new TransactionScope()) {
   using (SqlConnection connection = new SqlConnection(connectionString)) {
      connection.Open();
      connection.Close();
      connection.Open(); // escalates to DTC
   }
}

因此我可以理解是否每个调用SqlConnection.Open()都从连接池中获取。

如果在打开之前使用SqlTableAdapter来阻止该连接,SqlTableAdapter将打开并关闭连接,有效地为你完成事务。

因此,基本上,为了成功地使用SQL2005的TransactionScope,你需要有某种全局连接对象,从第一个TransactionScope的点一直保持开放,直到不再需要它为止。除了一个全局连接对象的代码,首先打开连接并关闭它,这与尽可能晚打开连接的逻辑以及尽快关闭连接的逻辑是不一致的。

EN

Stack Overflow用户

发布于 2018-02-26 15:05:24

TransactionScope总是升级到DTC事务,如果你在内部使用了超过1个连接,以上代码可以DTC禁用从连接池中获取两次相同的链接。

“问题是,在我们一半的开发人员机器上,我们可以在禁用MSDTC的情况下运行”。

票数 0
EN
查看全部 6 条回答
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/-100007436

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档