Связать между собой вызовы методов НачатьТранзакцию() и Форма.ОткрытьМодально() непосредственно путем анализа кода конфигурации получается далеко не всегда: это может быть как очень трудоемко, так и вовсе невозможно, если, например, код вызывается из внешней обработки.
Ловить такие связки, однако, нужно, т. к. их последствия могут быть очень серьезными (см. раздел 4.27). Чтобы поймать ее для случая из раздела 4.27, когда в транзакции модально открывалась форма списка, из которой шла интерактивная работа с документами, обратим внимание на то, что вообще-то открытие формы документа не должно выполняться в транзакции. То есть наличие активной транзакции в процедуре ПриОткрытии() формы документа может являться маркером неправильного поведения.
Процедура ПриОткрытии()
Если ТранзакцияАктивна() тогда
// каким-то образом вытащить стек вызовов в доступное место
КонецЕсли;
...
Удобным способом получить стек вызовов является вывод в технологический журнал сервера «1С:Предприятия». Однако, поскольку процедура ПриОткрытии() выполняется на клиенте, далеко не любое событие (в т. ч. исключение) окажется именно в серверном журнале, а не в клиентском. Подходящим является событие SDBL. Ниже приводится пример решения задачи.
Настроим logcfg.xml:
?xml version="1.0"?>
config xml="http://v8.1c.ru/v8/tech-log">
log history="24" location="D:\LOGS1c">
event>
eq property="Name" value="SDBL"/>
like property="Sdbl" value="%АктивнаяТранзакцииВПриОткрытии%"/>
/event>
property name="all"/>
/log>
/config>
На месте АктивнаяТранзакцииВПриОткрытии может быть любая уникальная последовательность символов, которую можно использовать в качестве фильтра. Если все настроено правильно, в технологическом журнале не будет других событий.
В процедуре ПриОткрытии() формы документов, отметившихся в журнале регистрации, включаем код:
Процедура ПриОткрытии()
...
Если ТранзакцияАктивна() тогда
ЗапросЛовушкаОшибкиДляАктивнойТранзакции = Новый Запрос;
ЗапросЛовушкаОшибкиДляАктивнойТранзакции.Текст = "ВЫБРАТЬ
| ""АктивнаяТранзакцииВПриОткрытии"" КАК Поле1";
Результат = ЗапросЛовушкаОшибкиДляАктивнойТранзакции.Выполнить();
КонецЕсли;
Если выполнение действий требуется пресекать, можно вызывать исключение. Чтобы вывести значения переменных или другую информацию о происходящем, например ЭтоНовый(), нужно использовать параметры запроса:
Процедура ПриОткрытии()
Если ТранзакцияАктивна() тогда
ЗапросЛовушкаОшибкиДляАктивнойТранзакции = Новый Запрос;
ЗапросЛовушкаОшибкиДляАктивнойТранзакции.Текст = "ВЫБРАТЬ
| ""АктивнаяТранзакцииВПриОткрытии"" КАК Поле1,
| &Параметр1 КАК Поле2"; ЗапросЛовушкаОшибкиДляАктивнойТранзакции.УстановитьПараметр("Параметр1", ЭтоНовый());
Результат = ЗапросЛовушкаОшибкиДляАктивнойТранзакции.Выполнить();
ВызватьИсключение "АктивнаяТранзакцииВПриОткрытии"; // это по желанию. Можно вызывать, чтобы не давать выполняться.
КонецЕсли;
Если ловушка срабатывает, в серверном технологическом журнале виден стек вызовов, а также текст запроса с фактическими значениями параметров (в нашем случае ЭтоНовый() = FALSE):
47:21.9647-3,SDBL,4,process=rphost,p:processName=bp20,t:clientID=110198,t:applicationName=1CV8,t:computerName=SRV-PRL-EXP-01,t:connectID=93632,SessionID=45,Usr=DefUser,Trans=1,Sdbl='SELECT
"АктивнаяТранзакцииВПриОткрытии",
FALSE
',Rows=1
47:21.9651-0,Context,3,process=rphost,p:processName=bp20,t:clientID=110198,t:applicationName=1CV8,t:computerName=SRV-PRL-EXP-01,t:connectID=93632,SessionID=45,Usr=DefUser,Context='
{Документ.РасходныйКассовыйОрдер.Форма.ФормаСписка}
Форма.Форма1.Форма : 5 : Форма = Документы.РасходныйКассовыйОрдер.ПолучитьФормуСписка().ОткрытьМодально();
Документ.РасходныйКассовыйОрдер.Форма.ФормаДокумента.Форма : 612 : Результат = ЗапросЛовушкаОшибкиДляАктивнойТранзакции.Выполнить();'
Описанный выше способ получения стеков вызовов и значений переменных годится и в других ситуациях, когда проблема воспроизводится эпизодически и/или отладка недоступна. Например, его можно применять для поиска ошибок: