TransactionScope автоматически переходит в MSDTC на некоторых машинах?

В нашем проекте мы'используя TransactionScope's, чтобы гарантировать, что наш уровень доступа к данным выполняет это 'действия в транзакции. Мы'повторно стремиться кне требует, чтобы служба MSDTC была включена на нашем конечном пользователес машины.

Проблема в том, что на половине машин наших разработчиков мы можем работать с отключенным MSDTC. Другая половина должна включить его, или они получают "MSDTC на [SERVER] недоступен " сообщение об ошибке.

Это'Это действительно заставило меня почесать голову, и я серьезно подумываю о том, чтобы вернуться к самодостаточному TransactionScope-подобному решению на основе объектов транзакций ADO.NET. Это'с на первый взгляд безумный - тот же код, который работает (и не расширяется) на половине нашего разработчикаделает эскалировать на другого разработчикаs.

Я надеялся на лучший ответОтследить, почему транзакция переходит в 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();
}

Мы'я действительно закопался и попытался понять это. Вот'Немного информации о машинах, на которых он работает:

Dev 1: Windows 7 x64 SQL2008Dev 2: Windows 7 x86 SQL2008Dev 3: Windows 7 x64SQL2005 SQL2008

Разработчики это не 'работать над:

Dev 4: Windows 7 x64,SQL2008 SQL2005Dev 5: Windows Vista x86, SQL2005Дев 6: Windows XP X86, SQL2005Мой домашний ПК: Windows Vista Home Premium, x86, SQL2005

Я должен добавить, что все машины, чтобы выследить проблему, были полностью исправлены всем, чтоДоступно из Центра обновления Microsoft.

Обновление 1:http://social.msdn.microsoft.com/forums/en-US/windowstransactionsprogramming/thread/a5462509-8d6d-4828-aefa-a197456081d3/ описывает подобную проблему ... еще в 2006 году!http://msdn.microsoft.com/en-us/library/system.transactions.transactionscope%28VS.80%29.aspx - прочитайте этот пример кода, он ясно демонстрирует соединение с вложенной секундой (фактически, со вторым сервером SQL), которое переходит в DTC.Мы не делаем это в нашем коде - мымы не используем разные SQL-серверы, ни разные строки подключения, ни открытие вложенных дополнительных подключений -не должно быть эскалации к DTC.http://davidhayden.com/blog/dave/archive/2005/12/09/2615.aspx (с 2005 года) рассказывает о том, как эскалация к DTC всегда будет происходить при подключении к SQL2000. Мы'использовать SQL2005 / 2008http://msdn.microsoft.com/en-us/library/ms229978.aspx MSDN об эскалации транзакций.

На этой странице эскалации транзакций MSDN указано, что при следующих условиях транзакция переходит в DTC:

По крайней мере один долговременный ресурс, который не поддерживает однофазные уведомления, зачислен в транзакцию.По крайней мере два долговременных ресурса, которые поддерживают однофазные уведомления, зачисляются в транзакцию. Например, использование одного соединения с не приводит к продвижению транзакции. Однако всякий раз, когда вы открываете второе соединение с базой данных, в результате чего база данных подключается, инфраструктура System.Transactions обнаруживает, что это второй долговременный ресурс в транзакции, и преобразует его в транзакцию MSDTC.Просьба к "предводитель» транзакция в другой домен приложения или другой процесс вызывается. Например, сериализация объекта транзакции через границу домена приложения. Объект транзакции является маршалированным по значению, что означает, что любая попытка передать его через границу домена приложения (даже в том же процессе) приводит к сериализации объекта транзакции. Вы можете передать объекты транзакции, вызвав удаленный метод, который принимает транзакцию в качестве параметра, или вы можете попытаться получить доступ к удаленному компоненту, обслуживаемому транзакцией. Это сериализует объект транзакции и приводит к эскалации, как при сериализации транзакции в домене приложения. Он распространяется, и локальный менеджер транзакций больше не подходит.

Мы'не испытывает # 3. # 2 не происходит, потому что есть только одно соединение за раз, и это 'также к одномудолговечный ресурс, Есть ли способ, которым # 1 могло случиться? Некоторая конфигурация SQL2005 / 8, которая заставляет его не поддерживать однофазные уведомления?

Обновление 2:

Пересмотрел лично каждоговерсии SQL Server - "Dev 3 " на самом деле имеет SQL2008, и "Dev 4 " на самом деле SQL2005. Тот'научу меня никогда больше не доверять моим коллегам. ;) Из-за этого изменения данных, я 'я уверен, что мымы нашли нашу проблему. Наши разработчики SQL2008 не былиПроблема возникла из-за того, что в состав SQL2008 включено огромное количество замечательных компонентов, которых нет в SQL2005.

Это также говорит мне, что, потому что мыбудет поддерживать SQL2005, что мы можемне использовать TransactionScope, как мы, и если мы хотим использовать TransactionScope, мы 'нам нужно будет передать один объект SqlConnection вокруг ... что кажется проблематичным в ситуациях, когда SqlConnection может 'его легко обойти ... просто пахнет экземпляром global-SqlConnection. Pew!

Обновление 3

Просто чтобы уточнить здесь в вопросе:

SQL2008:

Позволяет несколько подключений в пределах одного TransactionScope (как показано в приведенном выше примере кода).Предупреждение # 1: Если эти несколько SqlConnections вложены, то есть два или более SqlConnections открываются одновременно, TransactionScope немедленно переходит в DTC.Предостережение № 2: Если дополнительное SqlConnection открыто для другогодолговечный ресурс (т. е. другой SQL-сервер), он немедленно переходит в DTC

SQL2005:

Не разрешает множественные соединения в пределах одного TransactionScope, точка. Он будет увеличиваться, если / если открыт второй SqlConnection.Обновление 4

В интересах сделать этот вопрос еще болеебеспорядка полезно, и просто для большей ясностиради, здесьКак вы можете заставить SQL2005 перейти на DTC с помощьюне замужем :SqlConnection

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

Это просто кажется мне сломанным, но я думаю, я могу понять, если каждый звонокSqlConnection.Open() захватывает из пула соединений. "

Почему это может случиться? " Хорошо, если вы используете SqlTableAdapter против этого соединения перед этимПосле открытия SqlTableAdapter откроет и закроет соединение, фактически завершив транзакцию за вас, потому что теперь вы можете 'не открывай его

Таким образом, в основном, чтобы успешно использовать TransactionScope с SQL2005, вам нужно иметь какой-то глобальный объект соединения, который остается открытым с момента создания первого TransactionScope до тех пор, пока он не будет 'больше не нужны. Помимо запаха кода глобального объекта соединения, открытие первого соединения и его закрытие последним противоречит логике открытия соединения как можно позже и его закрытия как можно скорее.