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