При обновлении конфигураций на платформе 1С:Предприятие 8.3 (особенно это касается релизов веток 8.3.8–8.3.10) программисты и администраторы часто сталкиваются с критической ошибкой. В процессе выполнения обработчиков обновления информационной базы система выдает сообщение: Ошибка при вызове метода контекста (ЭтотУзел): Найдено более одной записи. Чаще всего это происходит в общем модуле ОбменСообщениямиВнутренний или при работе с планами обмена в распределенных информационных базах (РИБ).
В этой статье мы подробно разберем, почему возникает эта коллизия, как продиагностировать проблему и какими способами можно вернуть базу в работоспособное состояние.
Для начала проанализируем ситуацию с технической точки зрения. В любом плане обмена в 1С существует так называемый «Предопределенный узел» — это запись, которая представляет текущую информационную базу. В программном коде к ней обращаются через метод ПланыОбмена.ИмяПланаОбмена.ЭтотУзел(). Логика платформы подразумевает, что такой узел в таблице может быть только один.
Ошибка возникает из-за нарушения логической или физической целостности таблиц базы данных. Это случается по нескольким причинам:
ЭтотУзел.ЭтотУзел() получает противоречивые данные.Прежде чем переходить к написанию кода, рассмотрим самый простой и зачастую наиболее эффективный метод — стандартную утилиту тестирования. Как показывает практика (и подтверждают участники обсуждения), современные версии платформы умеют автоматически исправлять подобные коллизии.
Выполним следующие шаги:
В большинстве случаев после завершения процедуры лишние записи в планах обмена будут удалены или переведены в статус обычных узлов, и ошибка исчезнет.
Проанализируем версию используемой платформы. Ошибка Найдено более одной записи была признана багом в ранних релизах 8.3.8. Если ваша версия ниже 8.3.12, настоятельно рекомендуем выполнить обновление технологической платформы до актуального стабильного релиза. Зачастую сама процедура обновления платформы и последующий запуск базы в режиме Предприятие инициируют автоматические механизмы исправления структуры таблиц.
Если автоматическое тестирование не помогло, нам придется вмешаться в структуру данных программно. Основная сложность здесь заключается в том, что платформа блокирует изменение предопределенных узлов в обычном режиме. Чтобы обойти это ограничение, мы будем использовать свойство ОбменДанными.Загрузка = Истина.
Рассмотрим пример кода, который поможет найти лишний узел и удалить его. Предположим, ошибка возникает в плане обмена ОбменСообщениями или ПоМагазину. Создадим внешнюю обработку и в модуле пропишем следующий алгоритм:
Процедура ИсправитьДублиПлановОбмена() Экспорт
// Выберем все узлы конкретного плана обмена, где ЭтотУзел = Истина
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Т.Ссылка КАК Ссылка,
| Т.Наименование КАК Наименование,
| Т.Код КАК Код
|ИЗ
| ПланОбмена.ОбменСообщениями КАК Т
|ГДЕ
| Т.ЭтотУзел = ИСТИНА";
РезультатЗапроса = Запрос.Выполнить();
Выборка = РезультатЗапроса.Выбрать();
// Если найдено больше одной записи, нужно оставить только одну
Если Выборка.Количество() > 1 Тогда
Пока Выборка.Следующий() Цикл
// Логика: оставляем узел с заполненным наименованием/кодом,
// а пустые или некорректные дубли удаляем.
Если ПустаяСтрока(Выборка.Наименование) Или Выборка.Код = "000" Тогда
ОбъектУзла = Выборка.Ссылка.ПолучитьОбъект();
// Включаем режим загрузки, чтобы обойти проверки платформы
ОбъектУзла.ОбменДанными.Загрузка = Истина;
Попытка
ОбъектУзла.Удалить();
Сообщить("Удален лишний узел: " + Выборка.Ссылка);
Исключение
// Если удаление невозможно, попробуем хотя бы снять признак ЭтотУзел
ОбъектУзла.ЭтотУзел = Ложь;
ОбъектУзла.Записать();
Сообщить("Не удалось удалить, снят признак 'ЭтотУзел': " + Выборка.Ссылка);
КонецПопытки;
КонецЕсли;
КонецЦикла;
Иначе
Сообщить("Дублей не обнаружено.");
КонецЕсли;
КонецПроцедуры
Важный момент: Если вы не уверены, какой именно узел является «лишним», посмотрите на его Наименование и Код. Обычно «правильный» узел заполнен данными вашей организации или магазина, а «фантомный» дубль может быть пустым или содержать дефолтные значения.
Иногда мы сталкиваемся с ситуацией, когда в базе данных всё в порядке (запрос возвращает одну запись), но платформа продолжает выдавать ошибку. Это явный признак проблем с кэшем метаданных. Разберем, как произвести полную очистку.
Для клиент-серверного варианта:
C:\Program Files\1cv8\srvinfo).snccntx и config (не трогайте файлы лицензий!).Для локального пользователя:
Просто удалим базу из списка в окне запуска 1С и добавим её заново. Это принудительно создаст новую папку локального кэша в каталоге %AppData%\1C\1cv8.
Прежде чем что-то удалять, проанализируем ситуацию через консоль запросов. Это поможет точно определить имя плана обмена, в котором произошел сбой. Выполним запрос:
ВЫБРАТЬ
"ОбменСообщениями" КАК ИмяПлана,
Ссылка,
ЭтотУзел,
ПометкаУдаления
ИЗ
ПланОбмена.ОбменСообщениями
ГДЕ
ЭтотУзел = ИСТИНА
Если в результате вы видите две и более строки — вы нашли виновника. Повторите этот запрос для всех подозрительных планов обмена (СинхронизацияДанныхЧерезУниверсальныйФормат, ПоМагазину, Полный и т.д.), если ошибка не указывает конкретное имя.
Если проблема возникла в РИБ, проанализируйте статус главного узла. Иногда помогает временное «отключение» базы от распределенной сети командой:
ПланыОбмена.УстановитьГлавныйУзел(Неопределено);
После этого база становится автономной, что позволяет легче манипулировать узлами планов обмена. После исправления данных не забудьте вернуть привязку к главному узлу.
Подведем итог: ошибка «Найдено более одной записи» в методе ЭтотУзел — это результат коллизии в данных. Сочетание Тестирования и исправления с программным методом ОбменДанными.Загрузка = Истина позволяет решить проблему без потери данных и продолжить обновление конфигурации.