Как добавить ссылку на справочник из расширения в регистр основной конфигурации при низком режиме совместимости

Программист 1С v8.3 (Управляемые формы) 1С:ERP Управление предприятием IT и автоматизация бизнеса
← На главную

При разработке расширений для крупных систем, таких как 1С:ERP или 1С:Комплексная автоматизация, программисты часто сталкиваются с жесткими ограничениями режима совместимости. Типичная ситуация: в основную конфигурацию, находящуюся на поддержке, нужно добавить функционал, использующий новый справочник из расширения. Если требуется записать ссылку на этот справочник в существующий регистр сведений (например, в измерение с типом ЛюбаяСсылка), платформа выдает ошибку. Это происходит из-за того, что в режимах совместимости ниже 8.3.17 расширение типов основной конфигурации типами из расширения запрещено.

В этой статье мы подробно разберем причины этой проблемы и проанализируем несколько проверенных способов её решения, от обновления платформы до архитектурных обходных путей.

Почему возникает проблема: технический анализ ситуации

Разберем ситуацию изнутри. Тип ЛюбаяСсылка в 1С — это не просто абстрактный указатель, а строго определенный набор идентификаторов таблиц СУБД, которые входят в состав метаданных основной конфигурации. Когда мы подключаем расширение, платформа пытается динамически сопоставить типы. В старых режимах совместимости (до версии 8.3.17) механизм расширений работает по принципу «строгой статической типизации» метаданных. Платформа физически не может «на лету» перестроить таблицу базы данных основного регистра, чтобы добавить в составной тип новый внутренний идентификатор таблицы из расширения.

Именно поэтому попытка добавить тип в расширении для измерения основного регистра приводит к ошибке: «Изменение типов недопустимо в режиме совместимости 8.3.17 и ниже». Платформа блокирует операцию, чтобы предотвратить нарушение логической целостности базы данных на уровне СУБД.

Решение 1: Повышение режима совместимости (Рекомендуемый путь)

Самый правильный и современный способ — это обновление платформы и повышение режима совместимости конфигурации до 8.3.17 и выше. Начиная с этой версии, 1С существенно переработала механизм работы расширений, позволяя динамически расширять составные типы (включая ЛюбаяСсылка).

Проанализируем шаги для выполнения этой задачи:

  1. Обновите платформу 1С:Предприятие на сервере и рабочих станциях до актуального релиза (например, 8.3.22 или выше).
  2. В свойствах основной конфигурации измените параметр «Режим совместимости». Если вы используете ERP, это потребует тщательного тестирования, так как изменение режима совместимости может повлиять на работу типовых механизмов.
  3. После обновления в расширении станет доступна возможность добавить основной регистр, выбрать его измерение и в окне редактирования типов отметить галочкой ваш справочник из расширения.

Однако, как справедливо замечено в обсуждении, обновление ERP — процесс длительный и сложный, а решение задачи может требоваться «здесь и сейчас». Рассмотрим альтернативы.

Решение 2: Создание параллельного регистра в расширении

Если менять основную конфигурацию нельзя, а режим совместимости не позволяет расширить типы, мы можем применить архитектурный маневр. Рассмотрим создание «связующего» регистра непосредственно в расширении.

Вместо того чтобы пытаться записать данные в типовой регистр, мы создаем новый регистр сведений в расширении со следующей структурой:

Проанализируем ситуацию на примере: нам нужно привязать новые свойства к «Заказу клиента». В типовом регистре мы этого сделать не можем. В нашем новом регистре в поле ОбъектОснования мы будем хранить ссылку на ДокументСсылка.ЗаказКлиента, а во втором поле — ссылку на наш новый справочник. В коде расширения (через &После или &Вместо) мы будем программно обращаться к нашему регистру, чтобы «подклеивать» данные к основным процессам.

Решение 3: Использование строкового представления (UUID)

Этот метод часто называют «строковым посредником». Он полезен, если в основном регистре есть текстовое поле или если можно добавить строковый ресурс в расширении к основному регистру. Суть заключается в том, что мы храним не саму ссылку, а её уникальный идентификатор в виде строки.

Рассмотрим, как это реализовать программно. При записи ссылки из расширения в строковое поле регистра мы выполняем следующий код:


// Получаем строковое представление UUID ссылки
СтрокаСсылка = Строка(СсылкаИзРасширения.УникальныйИдентификатор());
// Записываем эту строку в ресурс или измерение регистра (тип Строка 36 знаков)
МенеджерЗаписи = РегистрыСведений.ТиповойРегистр.СоздатьМенеджерЗаписи();
МенеджерЗаписи.Объект = СсылкаНаОбъектОснование;
МенеджерЗаписи.ДополнительныйИдентификатор = СтрокаСсылка;
МенеджерЗаписи.Записать();

Когда нам нужно получить объект обратно для работы, мы выполняем обратное преобразование:


// Читаем строку из регистра
СтрокаUUID = РесурсИзРегистра; 
// Восстанавливаем ссылку по имени справочника и UUID
НужнаяСсылка = Справочники.СправочникИзРасширения.ПолучитьСсылку(Новый УникальныйИдентификатор(СтрокаUUID));

Если Не НужнаяСсылка.Пустая() Тогда
    // Работаем с объектом
КонецЕсли;

Важное примечание: При таком подходе вы теряете возможность использовать стандартный поиск ссылок и не сможете строить запросы с соединением по этой ссылке в консоли отчетов, так как для базы данных это просто текст.

Решение 4: Использование типа ХранилищеЗначения

Если данные регистра используются редко (например, для хранения настроек) и по ним не требуется выполнять поиск или фильтрацию в запросах, можно упаковать ссылку в ХранилищеЗначения. Для этого в расширении добавьте к основному регистру новый ресурс с типом Произвольный.

Посмотрим на пример записи:


СсылкаИзРасширения = Справочники.МойСправочник.НайтиПоНаименованию("Тест");
МенеджерЗаписи = РегистрыСведений.ТиповойРегистр.СоздатьМенеджерЗаписи();
// ... заполнение ключевых измерений ...
МенеджерЗаписи.ДополнительныеДанные = Новый ХранилищеЗначения(СсылкаИзРасширения);
МенеджерЗаписи.Записать();

Этот метод обходит проверку типов при записи, так как содержимое хранилища сериализуется в бинарные данные. Однако помните, что это исключает индексацию данных.

Проблема обмена данными и планов обмена

Выясним причину опасений, упомянутых в сообщении 8 форума. Если вы используете типовой обмен (например, через РегистрСведений.СоответствияОбъектовИнформационныхБаз), то расширение типов не поможет само по себе. Типовые планы обмена «не знают» о существовании объектов из вашего расширения.

Чтобы подружить обмен и справочник из расширения, выполните следующие действия:

  1. В расширении создайте собственный план обмена или добавьте свои объекты в состав существующего (если платформа позволяет).
  2. Используйте подписки на события ПередЗаписьюРегистрации, чтобы вручную обрабатывать логику регистрации изменений для объектов расширения.
  3. В правилах конвертации данных (если используется КД 2.0) придется прописывать программную обработку таких узлов, передавая UUID объекта как строку.

Риски «битых ссылок» и удаления расширения

Проанализируем ситуацию, когда расширение отключается. Если вы записали данные справочника из расширения в таблицы основной базы (через UUID или другие хитрости), то при удалении расширения эти данные станут «призраками». Платформа не сможет автоматически очистить записи, так как ссылки станут невалидными, а таблицы расширения исчезнут.

Рекомендация: Всегда храните данные расширений в объектах расширений. Если вы создаете новый справочник в расширении, то и регистр для связи с ним лучше создавать в расширении. Это гарантирует, что при удалении расширения (например, при критическом сбое обновления) основная база останется «чистой» от неразрешимых ссылок.

Подводя итог, можно сказать: если есть возможность — обновляйте режим совместимости до 8.3.17. Если нет — используйте параллельный регистр в расширении как наиболее надежный и безопасный с точки зрения целостности данных метод.

← На главную