При обновлении конфигурации распределенной информационной базы (РИБ) системные администраторы и разработчики нередко сталкиваются с ситуацией, когда центральный узел успешно обновляется, но на подчиненных узлах при запуске в режиме «1С:Предприятие» выполнение процедур обновления аварийно прерывается.
Типичный пример такой ошибки возникает при работе процедур Библиотеки стандартных подсистем (БСП):
«РассылкаОтчетов.ЗарегистрироватьДанныеДляАктуализацииСпискаРегламентныхЗаданий отложенного обработчика обновления РассылкаОтчетов.АктуализироватьСписокРегламентныхЗаданий произошла ошибка: {ОбщийМодуль.ОбщегоНазначения.Модуль}: Ошибка при вызове метода контекста (Содержит): Возврат Метаданные.РегистрыСведений.Содержит(ОбъектМетаданных); по причине: Несоответствие типов (параметр номер 1)».
Разберем детально механизм возникновения этой неполадки и рассмотрим проверенные способы её устранения.
Проанализируем стек вызовов и поведение платформы. Ошибка Несоответствие типов при передаче параметра в метод Содержит() означает, что переменная ОбъектМетаданных содержит значение Неопределено вместо ссылки на объект метаданных. Это происходит из-за того, что прикладной код пытается получить метаданные предопределенного элемента (например, предопределенного элемента ЛичныеДанные справочника РассылкиОтчетов), но сам элемент физически отсутствует в таблице базы данных узла.
Выясним причину отсутствия предопределенного элемента в подчиненной базе:
Авто.Авто платформа интерпретирует как команду «Обновлять автоматически». Поэтому при первом старте или реструктуризации все предопределенные элементы создаются без сбоев.Авто строго как «Не обновлять автоматически». Архитектура РИБ предполагает, что данные должны приходить из главного узла через файлы обмена.В результате при старте подчиненного узла отрабатывают механизмы обновления конфигурации, процедура обращается к предопределенному элементу через точку, получает Неопределено, и дальнейшая работа прерывается исключением.
Наиболее надежный и правильный с точки зрения ссылочной целостности способ — выгрузить недостающий предопределенный элемент из центральной базы и загрузить его в подчиненный узел с сохранением внутреннего идентификатора (GUID).
Разберем по шагам порядок действий:
ВыгрузкаЗагрузкаДанныхXML находим справочник (в нашем случае РассылкиОтчетов) и выгружаем нужный предопределенный элемент (например, ЛичныеДанные) в файл XML./C ЗапуститьОбновлениеИнформационнойБазы снятым, если настроен автоматический запуск, либо входим под учетной записью без запуска фоновых заданий).Если нет возможности быстро выгрузить данные из центра, заставим платформу применить обновление предопределенных данных для подчиненного узла штатной командой пакетного запуска Конфигуратора.
Рассмотрим запуск через командную строку. Для этого выполним пакетное обновление с параметром /SetPredefinedDataUpdate -UpdateAutomatically:
"C:\Program Files\1cv8\common\1cv8.exe" CONFIG /F "D:\Bases\SubNode" /N "Администратор" /P "Пароль" /SetPredefinedDataUpdate -UpdateAutomatically /UpdateDBCfg
После успешного обновления конфигурации базы данных и создания необходимых записей запустим базу в режиме предприятия и дождемся завершения работы обработчиков. Затем обязательно вернем исходное состояние параметра для подчиненного узла:
"C:\Program Files\1cv8\common\1cv8.exe" CONFIG /F "D:\Bases\SubNode" /N "Администратор" /P "Пароль" /SetPredefinedDataUpdate -Auto
Посмотрим на программный метод решения проблемы. Платформа 1С предоставляет разработчику методы встроенного языка для точечного управления предопределенными данными конкретного метаданного без изменения всей конфигурации.
Создадим внешнюю обработку и выполним следующий код:
// Принудительно разрешаем создание элементов для конкретного справочника
Справочники.РассылкиОтчетов.УстановитьОбновлениеПредопределенныхДанных(ОбновлениеПредопределенныхДанных.ОбновлятьАвтоматически);
// Сбрасываем флаг инициализации, чтобы платформа выполнила повторный поиск элементов
Справочники.РассылкиОтчетов.УстановитьИнициализациюПредопределенныхДанных(Ложь);
// Обращаемся к элементу для инициализации его создания в таблице
Попытка
ТестоваяСсылка = Справочники.РассылкиОтчетов.ЛичныеДанные;
Исключение
Сообщить("Ошибка обращения к предопределенному элементу: " + ОписаниеОшибки());
КонецПопытки;
// Возвращаем режим в исходное значение
Справочники.РассылкиОтчетов.УстановитьОбновлениеПредопределенныхДанных(ОбновлениеПредопределенныхДанных.Авто);
Также на уровне всей информационной базы можно использовать метод:
УстановитьОбновлениеПредопределенныхДанныхИнформационнойБазы(ОбновлениеПредопределенныхДанных.ОбновлятьАвтоматически);
Важное предостережение: при локальной генерации предопределенного элемента в подчиненном узле платформой генерируется новый УникальныйИдентификатор. Если в будущем данный справочник будет добавлен в состав плана обмена, это может привести к появлению дубликатов или ошибкам слияния данных с главным узлом. Именно поэтому Способ 1 (перенос через XML) остается приоритетным.
Если база заблокирована на этапе входа и стандартные механизмы не срабатывают, применим классический способ с временным снятием признака подчиненного узла.
Разберем алгоритм:
ПланыОбмена.УстановитьГлавныйУзел(Неопределено);
// В качестве параметра передаем ссылку на узел центральной базы в плане обмена
Главный = ПланыОбмена.ПолнотекстовыйОбмен.НайтиПоКоду("ЦУ");
ПланыОбмена.УстановитьГлавныйУзел(Главный);
Рассмотренные подходы позволяют устранить ошибку Несоответствие типов и успешно завершить процедуру обновления любого подчиненного узла распределенной информационной базы.