Исключение "Операция недействительна для состояния транзакции" с использованием TransactionScope

У нас есть веб-сервис на сервере # 1 и база данных на сервере # 2. Для создания распределенной транзакции веб-служба использует область транзакций. Все правильно.

И у нас есть другая база данных на сервере №3. У нас были некоторые проблемы с этим сервером, и мы переустановили операционную систему и программное обеспечение. Мы настроили MSDTC и попытались использовать веб-службу с сервера №1 для связи с базой данных на этом сервере. И теперь после первого выбора в рамках транзакции мы получаем: The operation is not valid for the state of the transaction. Это исключение относится к каждому запросу веб-службы, если оно использует область транзакций. Сервер №2 и сервер №3 почти похожи. Разница может быть только в настройках. .NET framework 3.5 SP1 и SQL Server SP3 на всех серверах.

Полная стек:

System.Transactions.TransactionState.EnlistPromotableSinglePhase(InternalTransaction tx, IPromotableSinglePhaseNotification promotableSinglePhaseNotification, транзакционное атомное взаимодействие) в System.Transactions.Transaction.EnlistPromotableSinglePhase(IPromotableSinglePhaseNotification promotableSinglePhaseNotification) в System.Data.SqlClient.SqlInternalConnection.EnlistNonNull(Transaction t в System.Data.SqlClient.SqlInternalConnection.Enlist(Транзакция t в System.Data.SqlClient.SqlInternalConnectionTds.Activate(Transaction транзакция) в System.Data.ProviderBase.DbConnectionInternal.ActivateConnection(Transaction транзакция) в System.Data.ProviderBase.DbConnectionPool.GetConnection(DbConnection owningObject) в System.Data.ProviderBase.DbConnectionFactory.GetConnection(DbConnection owningConnection) в System.Data.ProviderBase.DbConnectionClosed.OpenConnection(DbConnection externalConnection, DbConnectionFactory connectionFactory) в System.Data.SqlClient.SqlConnection.Open() в NHibernate.Connection.DriverConnectionProvider.GetConnection() в NHibernate.Impl.SessionFactoryImpl.OpenConnection()

Я искал это сообщение, но не нашел подходящего решения. Итак, какие настройки следует проверить и что именно следует делать, чтобы исправить это?

Ответы

Ответ 1

Lanfear, я столкнулся с тем же сообщением об ошибке, и нашел решение. Ваша ситуация может быть иной, но я надеюсь, что вам будут полезны следующие знания.

System.Transactions.Transaction.Current.TransactionInformation.Status вернет статус текущей транзакции.

В каждом случае, когда исключение отправляется с сообщением The operation is not valid for the state of the transaction, когда я делаю шаг с помощью отладчика, я вижу, что статус "Прервано" до того, как будет выбрано исключение.

В моем случае проблема была вызвана вложением двух транзакций внутри друг друга и ошибочным прерыванием обоих, когда я хотел прервать только одно. По-видимому, если вы используете конструктор TransactionScope по умолчанию New TransactionScope() с двумя вложенными транзакциями, прерывание внутренней транзакции также прерывает внешнюю транзакцию. Решение состоит в использовании конструктора New TransactionScope(TransactionScopeOption.RequiresNew) Используя этот конструктор, внутренняя транзакция будет новой транзакцией и прервана, она не прервет внешнюю транзакцию.

Это решило мою проблему.

Ответ 2

Включение координатора распределенных транзакций разрешило проблему для меня (это было сделано на обеих машинах: тот, у которого есть веб-служба, и тот, у которого есть база данных. Не уверен, хотя если это необходимо для веб-службы).

Я выполнил описанные здесь шаги, чтобы включить DTC и добавить исключение в брандмауэр Windows: Включить сетевой доступ DTC для Windows Server 2008