При разработке систем обмена данными или построении единого пространства нормативно-справочной информации (НСИ) часто возникает задача синхронизации объектов между разными базами. Один из наиболее надежных способов — обеспечить идентичность Уникальных Идентификаторов (УИД/GUID) у объектов в разных узлах системы. Однако стандартное поведение платформы 1С подразумевает автоматическую генерацию нового идентификатора в момент записи. В этой статье мы разберем, как переопределить это поведение и «подсунуть» системе свой УИД именно в момент интерактивного создания элемента пользователем.
Прежде чем перейти к программной реализации, проанализируем ситуацию. Представим, что у нас есть внешняя система (например, сайт или другая база 1С), которая сообщает нам о необходимости создания элемента. Если пользователь создает этот элемент вручную (интерактивно), но мы заранее знаем, какой идентификатор должен быть у этого объекта для корректного сопоставления в будущем, нам необходимо вмешаться в стандартный процесс записи платформы. Рассмотрим подробнее способы реализации этой задачи.
Основным инструментом для решения нашей задачи является метод УстановитьСсылкуНового(). Этот метод позволяет назначить объекту конкретную ссылку еще до того, как он будет физически зафиксирован в таблице базы данных. Разберем по шагам, где и как его вызвать.
Наиболее подходящим местом для вызова этого метода при интерактивной работе является обработчик события формы ПередЗаписьюНаСервере. В этот момент данные уже переданы с клиента на сервер, но транзакция записи еще не привела к созданию записи в БД.
Рассмотрим пример кода, который необходимо разместить в модуле управляемой формы справочника:
&НаСервере
Процедура ПередЗаписьюНаСервере(Отказ, ТекущийОбъект, ПараметрыЗаписи)
// Проверяем, что это действительно новый объект
Если ТекущийОбъект.ЭтоНовый() Тогда
// Предположим, мы получили нужный нам УИД из параметров или вычислили его
СтрокаУИД = "550e8400-e29b-41d4-a716-446655440000";
НовыйGUID = Новый УникальныйИдентификатор(СтрокаУИД);
// Формируем ссылку на основе этого УИД
НужнаяСсылка = Справочники.ИмяВашегоСправочника.ПолучитьСсылку(НовыйGUID);
// Устанавливаем ссылку для записываемого объекта
ТекущийОбъект.УстановитьСсылкуНового(НужнаяСсылка);
КонецЕсли;
КонецПроцедуры
Важный нюанс: метод УстановитьСсылкуНового() работает только для объектов, которые еще не были записаны в базу данных. Если объект уже существует, попытка вызвать этот метод приведет к ошибке.
Существует более «элегантный» метод, который позволяет избежать манипуляций непосредственно в момент записи. Мы можем создать ссылку с нужным УИД еще до того, как форма создания будет открыта пользователю. Выясним, как это работает.
Если вы открываете форму программно (например, из списка или по кнопке в другой форме), вы можете заранее подготовить ссылку через менеджер справочника и передать её в параметрах открытия. Проанализируем пример кода:
// Код в месте вызова (например, в команде создания)
НужныйУИД = Новый УникальныйИдентификатор("...");
НоваяСсылка = Справочники.Контрагенты.ПолучитьСсылку(НужныйУИД);
ПараметрыФормы = Новый Структура;
ПараметрыФормы.Вставить("ЗначениеЗаполнения", Новый Структура("Ссылка", НоваяСсылка));
ОткрытьФорму("Справочник.Контрагенты.ФормаОбъекта", ПараметрыФормы);
В этом случае платформа при создании нового объекта в памяти сразу присвоит ему указанную ссылку. Это избавляет от необходимости писать код в обработчике ПередЗаписьюНаСервере.
Когда мы принудительно назначаем УникальныйИдентификатор, мы берем на себя ответственность за целостность базы данных. Платформа 1С не проверяет уникальность ссылки в момент вызова метода УстановитьСсылкуНового(). Проверка произойдет только в момент попытки записи в СУБД.
Если в базе данных уже существует элемент с таким УИД, система выдаст критическую ошибку нарушения уникальности. Чтобы этого избежать, перед установкой ссылки обязательно проверим её существование:
// Проверка перед использованием ссылки
СсылкаСуществует = Справочники.ИмяСправочника.НайтиПоСсылке(НужнаяСсылка);
Если СсылкаСуществует.Пустая() Тогда
ТекущийОбъект.УстановитьСсылкуНового(НужнаяСсылка);
Иначе
// Обработка ситуации: УИД уже занят другим элементом
Сообщить("Внимание: Объект с таким идентификатором уже существует!");
Отказ = Истина;
КонецЕсли;
Рассмотрим дополнительные технические аспекты, которые могут повлиять на работу вашего решения:
УникальныйИдентификатор имеет ограниченную поддержку на стороне клиента в браузере. Всегда старайтесь выполнять генерацию и присвоение идентификаторов строго на стороне сервера (в серверных процедурах формы).&Перед для процедуры ПередЗаписьюНаСервере. Убедитесь, что основная конфигурация или другие расширения не переопределяют ссылку позже по стеку вызовов.ПолучитьСсылкуНового(), чтобы проверить, не была ли ссылка уже установлена ранее в коде.Посмотрим на ситуацию со стороны системного администратора и разработчика БД. Принудительная установка GUID, особенно если они генерируются не последовательно (случайным образом), может приводить к фрагментации индексов в MS SQL Server или PostgreSQL. Это происходит потому, что новые записи вставляются не в конец таблицы, а в произвольные места в соответствии со значением идентификатора.
Если ваша задача подразумевает массовое создание тысяч элементов в секунду с произвольными УИД, будьте готовы к тому, что производительность записи может быть несколько ниже, чем при использовании стандартных механизмов генерации 1С, которые оптимизированы для уменьшения фрагментации.
Мы выяснили, что для интерактивной установки конкретного УИД лучше всего подходит метод УстановитьСсылкуНового() в обработчике ПередЗаписьюНаСервере. Это решение позволяет гибко управлять идентификаторами в распределенных системах, сохраняя при этом возможность интерактивного ввода данных пользователем. Помните о необходимости предварительной проверки ссылки на существование и особенностях работы в веб-клиенте.