При попытке вызвать хранимую процедуру, содержащую инструкцию SELECT, я получаю следующую ошибку:
The operation is not valid for the state of the transaction
Вот структура моих звонков:
public void MyAddUpdateMethod()
{
using (TransactionScope Scope = new TransactionScope(TransactionScopeOption.RequiresNew))
{
using(SQLServer Sql = new SQLServer(this.m_connstring))
{
//do my first add update statement
//do my call to the select statement sp
bool DoesRecordExist = this.SelectStatementCall(id)
}
}
}
public bool SelectStatementCall(System.Guid id)
{
using(SQLServer Sql = new SQLServer(this.m_connstring)) //breaks on this line
{
//create parameters
//
}
}
Проблема в том, что я создаю другое соединение с той же базой данных в рамках транзакции?





Я столкнулся с этой ошибкой, когда моя транзакция вложена в другую. Возможно ли, что хранимая процедура объявляет собственную транзакцию или вызывающая функция объявляет ее?
+1, потому что я получил эту ошибку, когда язык транзакции в моей сохраненной процедуре был неправильным, то есть подсчет транзакций перепутался.
После некоторого исследования мне кажется, что я не могу открыть два соединения с одной и той же базой данных с помощью блока TransactionScope. Мне нужно было изменить свой код, чтобы он выглядел так:
public void MyAddUpdateMethod()
{
using (TransactionScope Scope = new TransactionScope(TransactionScopeOption.RequiresNew))
{
using(SQLServer Sql = new SQLServer(this.m_connstring))
{
//do my first add update statement
}
//removed the method call from the first sql server using statement
bool DoesRecordExist = this.SelectStatementCall(id)
}
}
public bool SelectStatementCall(System.Guid id)
{
using(SQLServer Sql = new SQLServer(this.m_connstring))
{
//create parameters
}
}
Я наткнулся на ту же ситуацию. Мне пришлось обратиться к двум разным базам данных в рамках одной и той же области транзакции. Спасибо за совет.
Хорошая уловка, обычное место, чтобы увидеть это, - это если у вас есть среда ведения журнала (nlog, log4net), которая выполняет запись в БД, поскольку структура ведения журнала создаст собственное соединение с базой данных в качестве вашего приложения.
Приложения регистрации должен, вероятно, подавляют любой внешний контекст TransactionScope.
NLog подавляет любую внешнюю TransactionScope: github.com/NLog/NLog/wiki/Database-target
Я дважды открывал одно и то же соединение с помощью операторов using в том же TransactionScope, но все еще работал. Я использовал SqlConnection вместо SQLServer, как в вашем примере выше.
Я также столкнулся с той же проблемой, я изменил тайм-аут транзакции на 15 минут, и он работает. Надеюсь, это поможет.
TransactionOptions options = new TransactionOptions();
options.IsolationLevel = System.Transactions.IsolationLevel.ReadCommitted;
options.Timeout = new TimeSpan(0, 15, 0);
using (TransactionScope scope = new TransactionScope(TransactionScopeOption.Required,options))
{
sp1();
sp2();
...
}
Я сильно подозреваю, что поведение изменилось не из-за тайм-аута, а из-за того, что вы изменили уровень изоляции с Serializable на ReadCommitted.
Когда я столкнулся с этим исключением, было InnerException «Время ожидания транзакции». Поскольку это было во время сеанса отладки, когда я на некоторое время остановил свой код внутри TransactionScope, я решил проигнорировать эту проблему.
Когда это конкретное исключение с тайм-аутом появляется в развернутом коде, я думаю, что следующий раздел в вашем файле .config поможет вам:
<system.transactions>
<machineSettings maxTimeout = "00:05:00" />
</system.transactions>
То же, что и TransactionOptions.Timeout?
Обратите внимание, что есть конфигурация .NET framework, которая отменяет это, когда это более 10 минут!
Для меня эта ошибка возникла, когда я пытался откатить блок транзакции после возникновения исключения внутри другого блока транзакции.
Все, что мне нужно было сделать, чтобы исправить это, - это удалить мой внутренний блок транзакции.
При использовании вложенных транзакций все может стать довольно запутанным, лучше всего этого избежать и просто реструктурировать свой код.
Для любого странника, который столкнется с этим в будущем. Если ваше приложение и база данных находятся на разных машинах и вы получаете указанную выше ошибку, особенно при использовании TransactionScope, включите доступ к сети DTC. Для этого нужно:
Важный: не редактируйте / не меняйте учетную запись пользователя и пароль в поле учетной записи DTC Logon, оставьте все как есть, в конечном итоге вам придется переустановить Windows, если вы это сделаете.
Это было исправлением нашей ситуации. Спасибо!
У меня нет кода транзакции t-sql ни в одной из хранимых процедур. Теоретически транзакция должна контролироваться MyAddUpdateMethod ()