В процессе разработки, переноса доработок между контурами или при настройке обменов данными разработчики иногда сталкиваются с ситуацией, когда одно и то же значение перечисления в разных информационных базах имеет разные уникальные идентификаторы (GUID / UUID). Это приводит к ошибкам сопоставления объектов или дублированию при интеграциях.
Перечисление в платформе 1С имеет двойственную природу: с одной стороны, его состав задается в дереве метаданных конфигурации, а с другой стороны, в базе данных каждое значение выступает полноценным ссылочным типом данных. Во встроенном языке 1С нет штатного метода вроде УстановитьСсылкуНового() для значений перечислений. Разберем доступные способы решения этой задачи, а также проанализируем сопутствующие риски.
Самый прямой и корректный с точки зрения целостности структуры метаданных способ — это редактирование описания объекта в исходных файлах конфигурации.
Рассмотрим пошаговый регламент выполнения этой операции:
Enums/ИмяПеречисления.xml).EnumValue или Value), и отредактируем значение атрибута uuid, указав требуемый GUID.Проанализируем, что произойдет с данными в информационной базе после смены идентификатора. Если в базе уже были документы, справочники или регистры, в которых было выбрано старое значение перечисления, после обновления платформой базы данных эти ссылки станут битыми — на их месте отобразится строка вида <Объект не найден>.
Платформа хранит ссылки на значения перечислений в таблицах СУБД в виде бинарного 16-байтного идентификатора _IDRREF. Так как старый GUID удален из метаданных, СУБД не сможет сопоставить старую бинарную ссылку с обновленным перечислением.
Чтобы избежать появления битых ссылок, выполним один из следующих сценариев:
НайтиПоСсылкам() и заменяем битые ссылки на обновленное значение.Если нет возможности выгружать всю конфигурацию в файлы, разберем альтернативный путь через поэтапное обновление информационной базы:
Значение_Новое).Посмотрим на пример кода на встроенном языке 1С, который позволяет получить соответствие имен значений перечисления и их номеров порядка (_ENUMORDER) в физической таблице базы данных:
Функция СоздатьТаблицуПеречислений(ИмяПеречисления)
Массив = Новый Массив;
Массив.Добавить("Перечисление." + ИмяПеречисления);
СтруктураБД = ПолучитьСтруктуруХраненияБазыДанных(Массив, Истина);
СтрТаблицы = СтруктураБД.Найти("Перечисление." + ИмяПеречисления, "ИмяТаблицы");
Мета = Метаданные.Перечисления[ИмяПеречисления];
ОбъектПеречисление = Перечисления[ИмяПеречисления];
ТекстЗапроса = "SELECT _IDRREF AS Ссылка, CASE ";
Для Каждого ЗначениеМета Из Мета.ЗначенияПеречисления Цикл
ИндексЗначения = ОбъектПеречисление.Индекс(ОбъектПеречисление[ЗначениеМета.Имя]);
ТекстЗапроса = ТекстЗапроса + " WHEN _ENUMORDER = " + ИндексЗначения + " THEN '" + ЗначениеМета.Имя + "'";
КонецЦикла;
ТекстЗапроса = ТекстЗапроса + " END AS ИмяЗначения FROM " + СтрТаблицы.ИмяТаблицыХранения + ";";
Возврат ТекстЗапроса;
КонецФункции
Иногда разработчики рассматривают вариант прямого обновления ссылок в таблицах СУБД с помощью скриптов, подобных следующему пакетному обновлению:
DECLARE @table TABLE(row_n INT IDENTITY(1,1), table_n NVARCHAR(500), col_n NVARCHAR(500))
DECLARE @iterator INT = 1
DECLARE @query NVARCHAR(1024)
INSERT INTO @table(table_n, col_n)
SELECT TABLE_NAME, COLUMN_NAME
FROM INFORMATION_SCHEMA.COLUMNS
WHERE DATA_TYPE = 'binary' AND COLUMN_NAME LIKE '%Ref%' AND CHARACTER_MAXIMUM_LENGTH = 16
WHILE @iterator <= (SELECT MAX(row_n) FROM @table)
BEGIN
SELECT @query = 'UPDATE ' + table_n + ' SET ' + col_n + ' = 0x8D4300155D007A5E11E3E65DF3EFDBB6 WHERE ' + col_n + ' = 0x8D4300155D007A5E11E3E57BD49E16A2'
FROM @table WHERE row_n = @iterator
EXEC sys.sp_executesql @query
SET @iterator = @iterator + 1
END
Важно понимать: прямая модификация таблиц базы данных в обход платформы 1С не рекомендуется по следующим причинам:
_IDRREF) различается из-за специфического порядка байтов платформы.Наиболее безопасным и надежным методом остается редактирование файлов выгрузки конфигурации с последующей регламентной обработкой ссылок средствами платформы.