19 апреля, 2024

Предопределенные элементы

В распределенной базе 1с версии 8.2 возникла следующая проблема: при обмене в результате какого-то сбоя появились дубликаты предопределнных элементов в плане характеристик, т.е. все записи имели двойника, все были отмечены как «предопределнный», имели одинаковый код и т.д. Пытаясь вылечить этот глюк я узнал интересную особенность этих элементов — при удалении такого элемента в базе, что можно сделать только программным способом, он больше не появляется в списке элементов, хотя и присутствует в конфигурации. Получается, что исправить эту ошибку можно только манипуляциями в базе данных, но не манипуляциями в конфигураторе.

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


//массив для выявления дубликатов
мНаименования = Новый Массив;

//структура, куда собираются уникальные элементы
Настройки = Новый Структура;

Выборка = ПланыВидовХарактеристик.НастройкиПользователей.Выбрать();

Пока Выборка.Следующий() Цикл

Если мНаименования.Найти(Выборка.Наименование) = Неопределено Тогда

мНаименования.Добавить(Выборка.Наименование);

Настройки.Вставить("КОД"+СокрЛП(Выборка.Код), Выборка.Ссылка);

Сообщить("+++ "+Выборка.Код+" "+Выборка.Наименование);

Продолжить;

КонецЕсли;

//если раскомментровать эти строки, будет выполнено удаление повторяющихся элементов
//Настройка = Выборка.ПолучитьОбъект();
//Настройка.Удалить();

КонецЦикла;

Если «дырок» в данных в результате удаления дубликатов нужно избежать, придется написать алгоритм посложнее. Я делал так — сначала перебором плана характеристик собирал структуру, содержащую по одному уникальному элементу, ключом элемента структуры был код из плана характеристик, а значение — сам элемент плана, затем перебирал записи регистра, в котором используется этот план, и заменял элемент в регистре элементом из структуры. Если документов или записей немного, возможно, проще и быстрее просто зачистить дубликаты и вручную восстановить пробелы в данных. Это хорошо сработало на центральной базе, однако, не помогло мне вылечить периферийную базу. Ошибка была в данных, которые поступали с обменом, а обмен не мог загрузиться, т.к. проверка уникальности записей запрещала ввод неуникальных значений в записи плана характеристик. Замкнутый круг.
Вот как я сделал. Переместил периферийную базу на один сервер с центральной базой. Отключил ее от главного узла. Загрузил конфигурацию, взятую с центральной базы. Сохранил изменения. Открыл таблицу, содержащую записи плана характеристик в менеджере SQL сервера и удалил из нее данные. С помощью sql-запроса скопировал записи из плана характеристик центральной базы в таблицу периферийной базы. Текст запроса очень простой, вот пример:

USE [DB2]
INSERT [_Reference20]
(_IDRRef,
_Code,
_Marked,
_PredefinedID,
_Description,
_Fld151,
_Fld152,
_Fld153)
SELECT
_IDRRef,
_Code,
_Marked,
_PredefinedID,
_Description,
_Fld477,
_Fld577,
_Fld586
FROM [DB1].dbo._Reference476
GO

Запрос удобен тем, что можно перечислить нужные поля. Если этого не делать и вместо списка полей указать звездочку «*», скорее всего получим ошибку, у меня так было с полем _Version и его я исключил. В приведенном коде DB2 — база приемник, DB1 — база источник. Таблица приемник — _Reference20, таблица источник — _Reference476. Поля копируются в том порядке, как они приведены в списке, например поле _Fld477 копируется в поле _Fld151.
После такой операции некоторые данные в регистрах, где были ссылки на этот план характеристик, были утеряны, но в целом работоспособность базы восстановилась, заработал обмен, конечно, после восстановления подключения к главному узлу.
Возможно, правильнее в этом случае было-бы совсем отказаться от дефектной периферийной базы и сделать новую, но в моем случае базы долго «не видели» друг друга и терять большой объем информации не хотелось. Да и не интересно решать проблемы такими простыми методами ;)