Недавно мне выпала честь тестировать документ, написанный чужой рукой. Сначала протестировал его в пользовательском режиме, потом потянуло меня посмотреть исходный код. Сразу обратил внимание на один участок. Выполняется запись нескольких объектов информационной базы - элемент справочника, элементы подчиненных справочников, записи регистров сведений. В общем, все эти записи логически связаны между собой. Но вот что смутило - ни обработки исключительных ситуаций, ни транзакции. При тестировании такая программа, конечно, скорее всего, выполнится без ошибок. Но в реальной работе в многопользовательском режиме есть риск возникновения исключительных ситуаций, связанных с конкурентным доступом к данным. Для разрешения проблем в подобных ситуациях используют транзакции.
Давайте разберемся, что такое транзакции, для чего они нужны, и как их правильно использовать. Транзакция - это группа последовательных операций, объединенных логикой выполнения приложения. Транзакция представляет собой логическую единицу работы с данными. Она может быть выполнена либо целиком и успешно, либо не выполнена вообще, и тогда она не должна произвести никакого эффекта. Другими словами, транзакция гарантирует логическую целостность данных.
В 1С для работы с транзакциями имеются три специальных процедуры:
- НачатьТранзакцию(<Режим блокировок>)
Открывает транзакцию. Необязательный параметр <Режим блокировок> типа РежимУправленияБлокировкойДанных может иметь значения Автоматический и Управляемый. Значение по умолчанию - Автоматический. - ЗафиксироватьТранзакцию()
Завершает успешную транзакцию. Все изменения, внесенные в информационную базу в процессе транзакции, будут записаны. - Отменить Транзакцию()
Отменяет открытую ранее транзакцию. Все изменения, внесенные в информационную базу в процессе транзакции, будут отменены.
Процедуры управления транзакциями удобно использовать совместно с оператором обработки исключительных ситуаций Попытка.
В качестве примера давайте рассмотрим участок кода, в котором записываются контрагент, договор контрагента и расчетный счет контрагента. Логика приложения такова, что мы должны либо успешно записать все три объекта, либо, в случае возникновения исключительной ситуации, полностью отменить операцию без каких-либо последствий для данных.
Попытка
НачатьТранзакцию();
КонтрагентОбъект = Справочники.Контрагенты.СоздатьЭлемент();
КонтрагентОбъект.Наименование = НаименованиеКонтрагента;
//Записываем другие реквизиты контрагента
КонтрагентОбъект.Записать();
КонтрагентСсылка = КонтрагентОбъект.Ссылка;
ДоговорОбъект = Справочники.ДоговорыКонтрагентов.СоздатьЭлемент();
ДоговорОбъект.Владелец = КонтрагентСсылка;
ДоговорОбъект.Наименование = НаименованиеДоговора;
//Записываем другие реквизиты договора
ДоговорОбъект.Записать();
РСОбъект = Справочники.БанковскиеСчета.СоздатьЭлемент();
РСОбъект.Владелец = КонтрагентСсылка;
РСОбъект.НомерСчета = НомерРасчетногоСчета;
//Записываем другие реквизиты договора
РСОбъект.Записать();
ЗафиксироватьТранзакцию();
Исключение
ОтменитьТранзакцию();
Сообщить(ОписаниеОшибки(), СтатусСообщения.Важное);
КонецПопытки;
Как это работает.
В случае успешного выполнения последовательности операторов попытки, оператор ЗафиксироватьТранзакцию() завершает транзакцию, записывая все изменения, внесенные в информационную базу. Далее управление передается оператору, следующему за ключевым словом КонецПопытки.
Если же в процессе выполнения операторов попытки происходит ошибка времени выполнения, то выполнение оператора, вызвавшего ошибку, прекращается и управление передается последовательности операторов исключения. Оператор ОтменитьТранзакцию() отменяет все изменения, внесенные в информационную базу в процессе транзакцию. Затем выдается сообщение об ошибке. Далее управление передается оператору, следующему за ключевым словом КонецПопытки.
Особо следует остановиться на транзакциях при проведении документов. С одной стороны, это типичный случай, когда необходимость транзакции очевидна. Но включать операторы управления транзакциями в процедуру обработки проведения документа нет необходимости, так как сама система включает их неявно. Так что любой документ по определению проводится в рамках транзакции.
Внутри транзакции крайне не рекомендуется использовать операторы, ожидающие отклик пользователя, такие как, например, Предупреждение(), Вопрос(), ВвестиЗначение() и т. п. И вообще время выполнения транзакций нужно стараться свести к минимуму. То же самое можно сказать и о проведении документов.
Надеюсь, что все понятно. Есть вопросы? Пишите, обсудим





Комментариев нет:
Отправить комментарий