gifts2017

Про ссылки, уникальные идентификаторы, GUID и не найденные объекты

Опубликовал Сергей (TSSV) в раздел Администрирование - Поиск данных

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

Про ссылки, GUID, уникальные идентификаторы и ненайденные объекты.

Одним из основных постулатов теории программирования в 1С является понятие объектного типа данных, когда мы говорим, что «удаление объекта  ссылочного типа из базы данных и затем создание нового объекта в базе с такими же точно реквизитами приведет базу в новое состояние, в отличие от случая с необъектными  данными (записи регистров и пр.)». И для новичков это так.

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

Итак, что же такое ссылка с точки зрения 1С? Ссылка - это тип данных, однозначно идентифицирующий объект в системе. А как ссылка соотносится с уникальным идентификатором (далее УИД) , получаемым методом УникальныйИдентификатор()?  УИД - это по сути свойство ссылки с типом УникальныйИдентификатор, строковое представление которого является 16-ричным числом и выглядит примерно так:

6a09f20a-8de6-11e1-b3e1-001617ec3f2a

К слову, УИД пустой ссылки всегда такой:

00000000-0000-0000-0000-000000000000

Итак, ссылка логически состоит из двух  частей – имени соответствующего объекта метаданных (тип ссылки), например «Справочник.Контрагенты»,  и УИДа, являющегося по своей природе GUIDом (об этом далее). Уникальность имени объекта метаданных контролируется платформой – вы не сможете создать двух справочников с одинаковым именем. Таким образом, ссылка является уникальной сущностью в пределах базы данных и это свойство (уникальности) обеспечивается двумя составляющими.

Теперь, для полноты картины, поговорим о том, что такое GUID.  По данным сайта wikipedia.org:

«GUID (Globally Unique Identifier) — статистически уникальный 128-битный идентификатор. Его главная особенность — уникальность, которая позволяет создавать расширяемые сервисы и приложения без опасения конфликтов, вызванных совпадением идентификаторов. Хотя уникальность каждого отдельного GUID не гарантируется, общее количество уникальных ключей настолько велико (2128 или 3,4028×1038), что вероятность того, что в мире будут независимо сгенерированы два совпадающих ключа, крайне мала. Тем не менее на системе Windows'95 GUID идентификаторы закладки свойств для ярлыка запуска DOS программ(.pif) и программы Zip Magic совпадали.» 
То есть, новые GUIDы получаются генерацией случайных чисел в диапазоне, сопоставимом с количеством атомов во Вселенной.

Таким образом, мы теперь понимаем, что при создании нового элемента объектного типа, в  платформе 1С запускается специальный генератор случайных чисел и получается GUID, который и записывается в качестве УИДа ссылки.

Может ли в базе 1С существовать два объекта с одинаковыми уникальными идентификаторами?  Да,  теоретически могут, но не в одной таблице (не в одном типе метаданных).  То есть,  мы можем иметь, например, элемент справочника «Номенклатура» и элемент справочника «Контрагенты» с одинаковым УИД и это нормально (на работоспособности системы это не скажется).

Можно ли зная УИД найти объект в базе? В общем случае нельзя, нужно дополнительно знать где искать – то есть таблицу данных, имя которой определяется именем объекта метаданных. Но, зная о том, что вероятностью совпадения GUID можно пренебречь, то на практике можно осуществлять поиск ссылки по УИД (например, анализируя файл выгрукзки данных в формате XML).

С теорией мы разобрались и теперь проведем небольшой эксперимент. Развенчаем миф о невозможности приведения системы в прежнее состояние после удаления объекта ссылочного типа. Использовать будем исключительно средства платформы 1С.

Во вложении пример обработки (для 8.2) с процедурой "УдалитьВосстановитьЭлемент", которая сначала удаляет элемент справочника по передаваемой ссылке, а потом создает новый такой же элемент (для простоты предполагается, что справочник не содержит табличных частей).  При этом, после удаления, ссылки на  элемент становятся "битыми" (объект не найдент...), а после воссоздания опять становятся "нормальными".         

Итак, миф развенчан, но признаем, что он был полезен нам в начале пути.

Теперь немного о практическом применении  полученных знаний. Всем известно такое явление, как «Объект не найден..», которое как известно возникает при удалении объектов без контроля ссылочной целостности.  При этом, в структуре надписи «Объект не найден …» содержится  GUID удаленной ссылки. Вот пример соответствия отображения "битой ссылки" и GUIDа этой ссылки:

Объект не найден (48:b3e2001617ec3f2a11e1912c787ec129)
787ec129-912c-11e1-b3e2-001617ec3f2a:

Здесь видно, что структура отображения ссылки и GUID соответствуют друг другу, но не совпадают. Мы сейчас не будем на этом  останавливаться, скажем только, что восстановить «битую» ссылку можно и этому посвящен ряд отдельных публикаций, например вот эта: http://infostart.ru/public/14655/

Анализируя XML файлы обмена, мы так же можем встретить знакомые уже GUIDы, которые можно в случае необходимости изменять  (такие задачи конечно же редки, но иногда могут встретиться).

Так же, иногда встречаются задачи, когда нам нужно создать и записать сразу два элемента справочника, где один элемент одновременно является владельцем другого и ссылается на него (например, элемент справочника "Номенклатура" с реквизитом "Основная единица измерения" с типом справочник "Единицы измерения", который в свою очередь подчинен номенклатуре).

Используя конструкции:

                УИД = Новый УникальныйИдентификатор();

                НоваяСсылка = Справочники[ИмяМетаданных].ПолучитьСсылку(УИД);

                НовыйЭлемент = Справочники[ИмяМетаданных].СоздатьЭлемент();

                НовыйЭлемент.УстановитьСсылкуНового(НоваяСсылка);

мы можем организовать запись каждого из элементов  за один раз.

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

Замечу, что использовать  данные механизмы нужно крайне осторожно, помня о возможных последствиях.

Вот пожалуй и все, что я хотел рассказать по данному вопросу,  хорошего кода!

Скачать файлы

Наименование Файл Версия Размер Кол. Скачив.
Пример работы с УИДами
.epf 6,98Kb
05.05.12
237
.epf 6,98Kb 237 Скачать

См. также

Подписаться Добавить вознаграждение

Комментарии

1. Владислав Чинючин (vcv) 06.05.12 09:19
объекта объектного типа

Гм. А объекты необъектного типа бывают?
Не путайте помянутых новичков терминологией. Объект может быть переменной объектного типа или экземпляром объектного типа. Но не бывает объектов объектного типа.
2. sergey_ts@list.ru (TSSV) 06.05.12 11:33
(1) vcv, Спасибо за проявленный интерес к публикации и заботу о новичках, которую полностью разделяю.
Позволю себе цитату с ресурса http://v8.1c.ru/:
"При манипулировании данными, хранящимися в базе данных 1С:Предприятия, зачастую используется объектный подход. Это значит, что обращение (чтение и запись) к некоторой совокупности данных, хранящихся в базе, происходит как к единому целому. Например, используя объектную технику, можно манипулировать данными справочников, документов, планов видов характеристик, планов счетов и т.д.

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

Эта ссылка также хранится в поле базы данных, вместе с остальными данными объекта. Кроме того, ссылка может быть использована как значение какого-либо поля другого объекта. Например, ссылка на объект справочника Контрагенты может быть использована как значение соответствующего реквизита документа ПриходнаяНакладная."
И все же думаю Вы правы - вместо "объектного типа" здесь лучше использовать формулировку "ссылочного типа" - так будет понятней о чем идет речь.
3. Ярослав Радкевич (WKBAPKA) 12.05.12 13:01
если честно, я не понял про уникальность... если УИД уникальный в пределах вселенной, т.е. вероятность совпадения невероятно мала, то фактически гарантируется уникальность ссылок в пределах всех информационных баз... это, конечно, если 1С придерживается алгоритма генерации гуида
4. Tsaregorodtsev@inbox.ru (TSSV) 14.05.12 09:39
(3) WKBAPKA, если мы исходим из того, что 1С придерживается (это конечно не документировано), то УИД уникальный в момент его создания, но, мы можем искусственно записать в базу один и тот же УИД в разные объекты разного типа (например, в элемент справочника "Номенклатура" и элемент справочника "Единицы измерения" - такие вещи могут встретиться при добавлении данных с помощью загрузки с использованием КД). И тогда УИД уже не уникален в пределах базы, но ссылки разные, так как ссылка это тип данных плюс УИД.
5. Ярослав Радкевич (WKBAPKA) 14.05.12 14:53
наверное так оно и есть... с одной стороны... а с другой, интересно, получится ли установить две одинаковые ссылки на один и тот же тип данных...
6. Dima Dima (dumal) 17.05.12 10:04
Замечательная статья. Спасибо Вам за нее
7. Юрий Курсин (Sherlock_kmw) 17.05.12 14:11
(5) WKBAPKA, нет не получится. в каждой из таблиц базы UUID является ключевым полем. отсюда и невозможность поиметь две номенклатуры с одним UUID
AleksR; TSSV; +2 Ответить
8. Дмитрий Леонов (Psylocibine) 20.05.12 22:48
А можно ли подменить UUID конкретного объекта?
9. Tsaregorodtsev (TSSV) 21.05.12 10:07
(8) Psylocibine, Подменить UUID конкретного объекта можно, но нужно помнить о ссылках на объект - они станут "битыми". Поэтому решение может быть следующим - создаем копию объекта с нужным УИДом, с помощью универсальной обработки "Поиск и замена значений" заменяем ссылки старого объекта на новый, удаляем старый объект. Так же мне приходилось решать задачу перевода метода синхронизации ряда справочников (контрагенты, номенклатура и пр.) с синхронизации по коду на синхронизацию по внутреннему идентификатору в работающей УПП (обмен был с БП) - то есть необходимо было массово заменить УИДы у большого количества элементов. Я поступил следующим образом - сделал полную выгрузку ИБ штатными механизмами УПП - "Выгрузка данных в идентичную конфигурацию" , в сформированном XML файле выгрузки сделал замену GUIDов (предварительно сформировав файл соответствия GUIDов), после чего загрузил переработанный файл выгрузки в пустую базу. Файл выгрузки редактировался как обычный текстовый файл, в каждой строке которого происходил поиск заменяемого GUIDа среди набора подлежащих замене и собственно сама замена. Метод себя оправдал - на операцию ушло несколько часов (не считая подготовки конечно) и в дальнейшем проблем с обменом не возникало.
Tangram; bashinsky; eruil; Kosstikk; +4 Ответить
10. Сергей (lsp71) 19.06.12 11:36
Хорошая статья. И написана понятным языком.
11. Юлия Петрова (petrovaUL) 10.07.12 06:12
12. Никита Коротаев (bforce) 02.09.12 11:51
Может ли в базе 1С существовать два объекта с одинаковыми уникальными идентификаторами? Да, теоретически могут, но не в одной таблице (не в одном типе метаданных). То есть, мы можем иметь, например, элемент справочника «Номенклатура» и элемент справочника «Контрагенты» с одинаковым УИД и это нормально (на работоспособности системы это не скажется).

Вот здесь написано иначе
Объект базы данных существует независимо от значений его реквизитов и имеет самостоятельную ценность. Например, у сотрудника может поменяться фамилия, номер паспорта и любые другие реквизиты. При этом он будет оставаться тем же самым физическим лицом.

После удаления объект нельзя создать заново. Даже если завести все его реквизиты в соответствии с удаленным объектом, это будет уже другой объект. Для объекта система хранит внутренний идентификатор — ссылку. Ссылка уникальна в пределах всей информационной базы. Двух объектов с одинаковыми ссылками не может существовать на всем протяжении жизни информационной базы. Ссылки удаленных объектов не присваиваются вновь созданным объектам. Система предоставляет возможность хранить в полях базы данных ссылки на объекты базы данных.

При условии, конечно, что вы будете использовать внутренние механизмы для генерации УИДов.
13. Роман Верховых (Lo1jke) 21.08.13 10:22
Спасибо, очень помоги, как раз занимался переносом XML нетипизированной партянки и нужно было насильно присваивать ГУИД.
14. Tsaregorodtsev (TSSV) 21.08.13 13:21
(13) Lo1jke, (10) рад что пригодилось, спасибо за отзывы!
Вот еще на эту тему: http://infostart.ru/public/192055/
15. Елена Волкова (volconok27) 27.09.13 07:58
Отличная статья. Как раз кстати. Спасибо
16. Марина Чирина (chmv) 05.11.13 16:27
17. Юрий Майоров (MaiorovYury) 01.04.14 11:18
18. Алекс Ю (AlexO) 18.07.14 09:20
(0)
При этом, в структуре надписи «Объект не найден …» содержится GUID удаленной ссылки.

Это логично, т.к. платформа натыкается на ссылку, получить которую не может, и генерирует на основе неё - ошибку "Объект не найден" с указанием "переработанной" исходной ссылки.
19. Алекс Ю (AlexO) 18.07.14 09:31
(0)
Итак, миф развенчан, но признаем, что он был полезен нам в начале пути.

Вы ничего не развенчали, а еще больше запутали новичков, для которых, якобы, все и "развенчивали".
Вы гарантируете, что после удаления ссылки те данные, на которые она ссылалась - осталось в целости и сохранности? Нет.
Вы гарантируете, что все подчиненные объекты "внутри" удаленного - остались на месте? Нет.
Так называемое "восстановление", да еще и громко названное
приведения системы в прежнее состояние после удаления объекта ссылочного типа

- не более чем создание и подгонка новых объектов под старые (битые) ссылки, а не восстановление старых объектов. Старые (и их содержимое) - потеряны навсегда.
А хотите "обмануть" систему - да пожалуйста, не надо ничего изобретать: создаете новый объект, удаляете старую ссылку, заменяете все старые - на новые.
Вуаля, ссылки восстановлены!
Т.е. статья написана "умно", но много воды, напущено тумана (для умности статьи?), и, главное, выводы сделаны совершенно неправильные (или двусмысленные - видимо, сам не разобрался).
20. Алекс Ю (AlexO) 18.07.14 09:39
(0)
Может ли в базе 1С существовать два объекта с одинаковыми уникальными идентификаторами? Да, теоретически могут, но не в одной таблице (не в одном типе метаданных).

Это сугубо Ваши домыслы.
1С ищет объект по ссылке, а не по "ссылка+тип данных", и что она должна вернуть, если по ссылке - два объекта?
Была теория, что 1С "зашифровала" тип даннных в ссылке, но пока она не получила ни подтверждения, ни полного отпровержения, т.к. ссылки формируются "подряд" (документ - ссылка №1, справочник - ссылка №2, документ - ссылка №3, ссылки по-порядку, последовательно, формируются), однако, и опровержение "зашифрованности" не получено от 1С.
21. Алекс Ю (AlexO) 18.07.14 09:51
(12) bforce,
Вот здесь написано иначе

Страничка удалена с ИТС.
22. Алекс Ю (AlexO) 18.07.14 10:03
(0)Tsaregorodtsev,
создавать новую ссылку:
УИД = Новый УникальныйИдентификатор();

НоваяСсылка = Справочники[ИмяМетаданных].ПолучитьСсылку(УИД);

НовыйЭлемент = Справочники[ИмяМетаданных].СоздатьЭлемент();

НовыйЭлемент.УстановитьСсылкуНового(НоваяСсылка);
...Показать Скрыть


нужно так:
УИД = Новый УникальныйИдентификатор();       

НовыйЭлемент = Справочники[ИмяМетаданных].СоздатьЭлемент();

НоваяСсылка = Справочники[ИмяМетаданных].ПолучитьСсылку(УИД);
...Показать Скрыть

Все.
И не надо тыркать по десять раз ссылку туда-сюда.
23. Алекс Ю (AlexO) 18.07.14 10:09
(0)Tsaregorodtsev,
А как ссылка соотносится с уникальным идентификатором (далее УИД)

Это UUID:
Объект не найден (48:b3e2001617ec3f2a11e1912c787ec129)


Это GIUD (назван "УИД" в 1С):
787ec129-912c-11e1-b3e2-001617ec3f2a:

А у вас туман один клубится в статье.
24. pavel ev (pavelyar) 23.12.14 16:17
Нет штатного средства поиска по GUID в конфиграциях и это очень плохо,под УФ тоже обработок не найти это беда...
25. Алекс Ю (AlexO) 04.06.15 10:05
(24) pavelyar,
Нет штатного средства поиска по GUID в конфиграциях
GUID как таковой вообще не используется в платформе 1С. Ссылки хранятся в формате UUID. Что и подтвержадет ошибка "Объект не найден (48:b3e2001617ec3f2a11e1912c787ec129)".
Для написания сообщения необходимо авторизоваться
Прикрепить файл
Дополнительные параметры ответа