Исключение "Операция недействительна для состояния транзакции" с использованием 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