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 до тех пор, пока он не будет 'больше не нужны. Помимо запаха кода глобального объекта соединения, открытие первого соединения и его закрытие последним противоречит логике открытия соединения как можно позже и его закрытия как можно скорее.

 PreguntonCojoneroCabrón07 янв. 2018 г., 23:56
Вложенные соединения в одной и той же области транзакции будут преобразованы в распределенную транзакцию. Начиная с SQL Server 2008 и выше, несколько (не вложенных) подключений в одной и той же области транзакции не будут преобразованы в распределенную транзакцию.
 brumScouse30 июл. 2012 г., 12:48
С точки зрения пула соединений, если у нас есть несколько соединений (и, если необходимо, вложенных), если мы открываем и закрываем по одному за раз, используем ли мы 1 реальный ресурс пула разрешений или 1 на соединение, я пытаюсь рационализировать это, чтобы определить иметь или нет соответствующую областьenlistable» подключение (которого я хотел бы избежать)
 Mathias F20 июн. 2014 г., 21:32
У меня была ошибка при подключении к SQLServer 2008 и использовании "Объединив = ложь» в ConnectionString. Весь день мои коллеги слышали, как я бормочуНо я тройку проверил: у меня 2008 "
 PreguntonCojoneroCabrón07 янв. 2018 г., 23:55
TransactionScope использует LTM - облегченный менеджер транзакций в .Net. Только если вы открываете более одного соединения в одной транзакции или переходите между базами данных, TransactionScope должен передать транзакцию DTC-менеджеру на базе 2PC. Для MS SQL Server 2008 и выше DTC будет задействован, только если вы открываете соединения с разными БД. ИЛИ, если вы открываете соединения в одних и тех же транзакциях из нескольких потоков, ЗА ИСКЛЮЧЕНИЕМ, если вы используете DependentTransaction, это то, что вам следует включить в глобальную транзакцию, если вы хотите выполнять многопоточность.
 axeman15 нояб. 2013 г., 00:09
Я наткнулся на этот вопрос, пытаясь найти причину исключения. Я'м, включая сведения об исключении, чтобы другие могли его найти.Network access for Distributed Transaction Manager (MSDTC) has been disabled. с внутренним исключениемThe transaction manager has disabled its support for remote/network transactions 0x8004D024  Программное обеспечение работало на многих сайтах, но не на нескольких. Оказывается, они использовали SQL2005, и, как указывает этот вопрос, им пришлось использовать MSDTC.
 Oran Dennison17 июл. 2012 г., 01:00
Большое спасибо за сообщение об обновлении 4, показывающее, как может произойти эскалация всего с одним SqlConnection. Это именно то, с чем я столкнулся, несмотря на тщательную проверку того, что используется только один SqlConnection. Это'приятно это знатькомпьютер, которыйсумасшедший и не я. :-)
 Joe07 нояб. 2009 г., 19:02
# 2 не происходит, потому что есть только одно соединение за раз " - № 2 неНе говоря уже о том, что второе соединение должно быть открыто одновременно, просто оно должно быть зачислено в ту же транзакцию.
 RichardOD07 нояб. 2009 г., 18:21
Можете ли вы расширить "Делайте здесь другие вещи, которые могут или не могут быть связаны с внешней транзакцией ", Конечно, то, что там, сильно влияет на поведение кода? "

Ответы на вопрос(6)

если вы используете доступ более чем к 1 соединению внутри. Единственный способ, с помощью которого приведенный выше код может работать с отключенным DTC, - это то, что при огромной вероятности вы оба раза получаете одно и то же соединение из пула соединений. "

Проблема в том, что на половине машин наших разработчиков мы можем работать с отключенным MSDTC ". Ты уверен, что уверен?с отключен;)

будут вызвать эскалацию при подключении к 2005 году.

Проверьте документацию на MSDN -http://msdn.microsoft.com/en-us/library/ms172070.aspx

Рекламные транзакции в SQL Server 2008

В версии 2.0 .NET Framework и SQL Server 2005 открытие второго соединения внутри TransactionScope автоматически переводит транзакцию в полную распределенную транзакцию, даже если оба соединения используют одинаковые строки подключения. В этом случае распределенная транзакция добавляет ненужные издержки, которые снижают производительность.

Начиная с SQL Server 2008 и версии 3.5 .NET Framework, локальные транзакции больше не преобразуются в распределенные транзакции, если в транзакции открывается другое соединение после закрытия предыдущей транзакции. Это не требует никаких изменений в вашем коде, если вы уже используете пул соединений и участвуете в транзакциях.

Я могу'Объяснить, почему Dev 3: Windows 7 x64, SQL2005 успешно, а Dev 4: Windows 7 x64 терпит неудачу. Вы уверены, что это не наоборот?

я вызываю локальный экземпляр сервера SQL, и он неT генерировать код неисправности ??

    public void DoWork2()
    {
        using (TransactionScope ts2 = new TransactionScope())
        {
            using (SqlConnection conn1 = new SqlConnection("Data Source=Iftikhar-PC;Initial Catalog=LogDB;Integrated Security=SSPI;"))
            {
                SqlCommand cmd = new SqlCommand("Insert into Log values(newid(),'" + "Dowork2()" + "','Info',getDate())");
                cmd.Connection = conn1;
                cmd.Connection.Open();
                cmd.ExecuteNonQuery();

                using (SqlConnection conn2 = new SqlConnection("Data Source=Iftikhar-PC;Initial Catalog=LogDB;Integrated Security=SSPI;Connection Timeout=100"))
                {
                    cmd = new SqlCommand("Insert into Log values(newid(),'" + "Dowork2()" + "','Info',getDate())");
                    cmd.Connection = conn2;
                    cmd.Connection.Open();
                    cmd.ExecuteNonQuery();
                }
            }

            ts2.Complete();
        }
    }
 Yoopergeek17 мая 2012 г., 22:53
Какой выпуск SQL Server вы используете?повторно используете? Интересно, Петер Мейнл?Ответ необходимо обновить, чтобы отразить любые изменения, внесенные в 2008R2 и / или Denali.I '
 Paul Zahra26 февр. 2013 г., 12:32
Не уверен, что проблема заключается во вложенном соединении? лол ... ну, блин, удаляй это! зачем же люди используют заявления, когда в этом нет необходимости, я?никогда не узнаешь.
 Yoopergeek17 окт. 2012 г., 19:24
Интересно, лучше ли ведет себя 2008 R2? Ответ @hwiechers также заставляет меня задуматься о том, какая у вас версия Framework?перекомпилирование против предотвращает эскалацию. Наконец, мне интересно, имеет ли это значение локальный экземпляр R2. Хотелось бы, чтобы у меня было время / ресурсы, чтобы изучить, как это изменилось с выпуском 2008 R2 и SQL Server 2012.
 Iftikhar Ali21 мая 2012 г., 21:41
м с использованием SQL Server 2008 R2.

почему этот ответ был удален, но, похоже, в нем есть какая-то соответствующая информация.

ответил 4 августа10 в 17:42Эдуардо

ЗадаватьПривлечь = ложь в строке подключения, чтобы избежать автоматического зачисления на транзакцию.

Вручную подключить соединение в качестве участников в объеме транзакции. [оригинальная статья устарела] или сделайте это:Как предотвратить автоматическое продвижение MSDTC[Archive.is]

 Kiquenet05 дек. 2017 г., 13:06
msdn.microsoft.com/en-us/library/ms172153%28v=VS.80%29.aspx не найдено, Visual Studio 2005 Документация в отставке
 Baig29 июл. 2011 г., 07:36
Спасибо, что поделились своими исследованиями. Это действительно помогло. Еще один быстрый запрос. В чем разница между TransactionScope () и sqlConnection.BeginTransaction ()?
 Frédéric20 июл. 2017 г., 14:43
Согласно этомузапрос функцииODAC 12C теперь должен вести себя как SQL 2008, не распространяясь на распределенные при использовании последовательных подключений к одному и тому же источнику данных.
Решение Вопроса

SQLConnectionв одномTransactionScope без эскалации, при условии, что соединения не открыты одновременно, что приведет кфизическое» TCP-соединения и, следовательно, требуют эскалации.

Я вижу, что у некоторых из ваших разработчиков есть SQL Server 2005, а у других - SQL Server 2008. Вы уверены, что правильно определили, какие из них обостряются, а какие нет?

Наиболее очевидным объяснением было бы то, что разработчики с SQL Server 2008 - это те, ктоэскалация

 Yoopergeek07 нояб. 2009 г., 22:24
Теперь у вас с hwiechers есть второе предположение, и яЯ стремлюсь приступить к работе в понедельник, более внимательно осмотреть их отдельные машины и убедиться, что версии SQL Server соответствуют ранее сообщенным.
 Yoopergeek07 нояб. 2009 г., 16:51
Да, детали верны, и кто-нибудь на самом деле смотрит на код? В области транзакции есть два соединения, однако только одно соединение создается и открывается в один момент времени. Кроме того, нет, DTC не работает на машинах, которые работают ".
 Eugene Beresovsky08 окт. 2013 г., 05:58
@Yoopergeek Я могу проверить, что ты "не одновременно важно и отредактировано @Joe 'ответь соответственно. Мониторинг соединений TCP во время тестирования показал, что старое соединение TCP будет использоваться повторно, если соединения не используются одновременно, и, следовательно,TransactionScope можно обойтись с однимCOMMIT на стороне сервера, что сделало бы эскалацию излишней.
 Yoopergeek09 нояб. 2009 г., 16:08
Вы и hwiechers правы. У меня яйцо по всему лицу. Спасибо за то, что ударили меня подсказкой. :) Потому что ты был первым, ты получил ответ. Я'Хотелось бы добавить одно пояснение - SQL2008 позволяет открывать несколько соединений, но не одновременно. В любой момент времени может быть открыто только одно соединение, иначе TransactionScope переходит в DTC.
 Joe07 нояб. 2009 г., 18:30
тем не менее, существует только одно соединение, которое создается и открывается в один момент времени " - почему это актуально? В SQL2005, если вы открываете более одного соединения в рамках транзакции, вы будете увеличивать, остаются ли они открытыми одновременно. Что логично, если вы думаете об этом.

Ваш ответ на вопрос