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

Одним из основных постулатов теории по программированию в 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, который и записывается в качестве УИДа ссылки.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

В начале публикации мы для упрощения понимания основной идеи мы считали, что GUIDы формируются как случайные числа в очень большом диапазоне, к тому же сама идея своей красотой заслуживает к себе внимания. Но, как уже упоминалось ранее, на самом деле в случае платформы 1С это не так — при формировании GUIDов используется время, о чем говорит "1" в первой позиции третьей секции (при случайной генерации на этой позиции "4"):

787ec129-912c-11e1-b3e2-001617ec3f2a

И связи с этим у нас появляется еще одна интересная возможность — получения времени генерации УИДа ссылки. Вот ссылка на публикацию с обработкой получения времени ссылки:

Получить дату создания документа или элемента справочника (по UID)

Подробнее о GUIDах можно прочитать здесь:

Руководство по GUID. Часть 1

Руководство по GUID. Часть 2

Руководство по GUID. Часть 3

32 Comments

  1. vcv
    объекта объектного типа

    Гм. А объекты необъектного типа бывают?

    Не путайте помянутых новичков терминологией. Объект может быть переменной объектного типа или экземпляром объектного типа. Но не бывает объектов объектного типа.

    Reply ↓
  2. TSSV

    (1) vcv, Спасибо за проявленный интерес к публикации и заботу о новичках, которую полностью разделяю.

    Позволю себе цитату с ресурса http://v8.1c.ru/:

    «При манипулировании данными, хранящимися в базе данных 1С:Предприятия, зачастую используется объектный подход. Это значит, что обращение (чтение и запись) к некоторой совокупности данных, хранящихся в базе, происходит как к единому целому. Например, используя объектную технику, можно манипулировать данными справочников, документов, планов видов характеристик, планов счетов и т.д.

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

    Эта ссылка также хранится в поле базы данных, вместе с остальными данными объекта. Кроме того, ссылка может быть использована как значение какого-либо поля другого объекта. Например, ссылка на объект справочника Контрагенты может быть использована как значение соответствующего реквизита документа ПриходнаяНакладная.»

    И все же думаю Вы правы — вместо «объектного типа» здесь лучше использовать формулировку «ссылочного типа» — так будет понятней о чем идет речь.

    Reply ↓
  3. WKBAPKA

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

    Reply ↓
  4. TSSV

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

    Reply ↓
  5. WKBAPKA

    наверное так оно и есть… с одной стороны… а с другой, интересно, получится ли установить две одинаковые ссылки на один и тот же тип данных…

    Reply ↓
  6. dumal

    Замечательная статья. Спасибо Вам за нее

    Reply ↓
  7. Sherlock_kmw

    (5) WKBAPKA, нет не получится. в каждой из таблиц базы UUID является ключевым полем. отсюда и невозможность поиметь две номенклатуры с одним UUID

    Reply ↓
  8. Psylocibine

    А можно ли подменить UUID конкретного объекта?

    Reply ↓
  9. TSSV

    (8) Psylocibine, Подменить UUID конкретного объекта можно, но нужно помнить о ссылках на объект — они станут «битыми». Поэтому решение может быть следующим — создаем копию объекта с нужным УИДом, с помощью универсальной обработки «Поиск и замена значений» заменяем ссылки старого объекта на новый, удаляем старый объект. Так же мне приходилось решать задачу перевода метода синхронизации ряда справочников (контрагенты, номенклатура и пр.) с синхронизации по коду на синхронизацию по внутреннему идентификатору в работающей УПП (обмен был с БП) — то есть необходимо было массово заменить УИДы у большого количества элементов. Я поступил следующим образом — сделал полную выгрузку ИБ штатными механизмами УПП — «Выгрузка данных в идентичную конфигурацию» , в сформированном XML файле выгрузки сделал замену GUIDов (предварительно сформировав файл соответствия GUIDов), после чего загрузил переработанный файл выгрузки в пустую базу. Файл выгрузки редактировался как обычный текстовый файл, в каждой строке которого происходил поиск заменяемого GUIDа среди набора подлежащих замене и собственно сама замена. Метод себя оправдал — на операцию ушло несколько часов (не считая подготовки конечно) и в дальнейшем проблем с обменом не возникало.

    Reply ↓
  10. lsp71

    Хорошая статья. И написана понятным языком.

    Reply ↓
  11. petrovaUL

    позновательно

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

    Вот здесь написано иначе

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

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

    При условии, конечно, что вы будете использовать внутренние механизмы для генерации УИДов.

    Reply ↓
  13. Lo1jke

    Спасибо, очень помоги, как раз занимался переносом XML нетипизированной партянки и нужно было насильно присваивать ГУИД.

    Reply ↓
  14. TSSV

    (13) Lo1jke, (10) рад что пригодилось, спасибо за отзывы!

    Вот еще на эту тему: http://infostart.ru/public/192055/

    Reply ↓
  15. volconok27

    Отличная статья. Как раз кстати. Спасибо

    Reply ↓
  16. chmv

    Спаасибо Интересно

    Reply ↓
  17. MaiorovYury

    Спасибо!

    Reply ↓
  18. AlexO

    (0)

    При этом, в структуре надписи «Объект не найден …» содержится GUID удаленной ссылки.

    Это логично, т.к. платформа натыкается на ссылку, получить которую не может, и генерирует на основе неё — ошибку «Объект не найден» с указанием «переработанной» исходной ссылки.

    Reply ↓
  19. AlexO

    (0)

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

    Вы ничего не развенчали, а еще больше запутали новичков, для которых, якобы, все и «развенчивали».

    Вы гарантируете, что после удаления ссылки те данные, на которые она ссылалась — осталось в целости и сохранности? Нет.

    Вы гарантируете, что все подчиненные объекты «внутри» удаленного — остались на месте? Нет.

    Так называемое «восстановление», да еще и громко названное

    приведения системы в прежнее состояние после удаления объекта ссылочного типа

    — не более чем создание и подгонка новых объектов под старые (битые) ссылки, а не восстановление старых объектов. Старые (и их содержимое) — потеряны навсегда.

    А хотите «обмануть» систему — да пожалуйста, не надо ничего изобретать: создаете новый объект, удаляете старую ссылку, заменяете все старые — на новые.

    Вуаля, ссылки восстановлены!

    Т.е. статья написана «умно», но много воды, напущено тумана (для умности статьи?), и, главное, выводы сделаны совершенно неправильные (или двусмысленные — видимо, сам не разобрался).

    Reply ↓
  20. AlexO

    (0)

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

    Это сугубо Ваши домыслы.

    1С ищет объект по ссылке, а не по «ссылка+тип данных», и что она должна вернуть, если по ссылке — два объекта?

    Была теория, что 1С «зашифровала» тип даннных в ссылке, но пока она не получила ни подтверждения, ни полного отпровержения, т.к. ссылки формируются «подряд» (документ — ссылка №1, справочник — ссылка №2, документ — ссылка №3, ссылки по-порядку, последовательно, формируются), однако, и опровержение «зашифрованности» не получено от 1С.

    Reply ↓
  21. AlexO

    (12) bforce,

    Вот здесь написано иначе

    Страничка удалена с ИТС.

    Reply ↓
  22. AlexO

    (0)Tsaregorodtsev,

    создавать новую ссылку:

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

    нужно так:

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

    Все.

    И не надо тыркать по десять раз ссылку туда-сюда.

    Reply ↓
  23. AlexO

    (0)Tsaregorodtsev,

    А как ссылка соотносится с уникальным идентификатором (далее УИД)

    Это UUID:

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

    Это GIUD (назван «УИД» в 1С):

    787ec129-912c-11e1-b3e2-001617ec3f2a:

    А у вас туман один клубится в статье.

    Reply ↓
  24. pavelyar

    Нет штатного средства поиска по GUID в конфиграциях и это очень плохо,под УФ тоже обработок не найти это беда…

    Reply ↓
  25. AlexO

    (24) pavelyar,

    Нет штатного средства поиска по GUID в конфиграциях

    GUID как таковой вообще не используется в платформе 1С. Ссылки хранятся в формате UUID. Что и подтвержадет ошибка «Объект не найден (48:b3e2001617ec3f2a11e1912c787ec129)».

    Reply ↓
  26. Videon

    Мне кажется, что «Ссылка — это тип данных,» взрывает мозг новичкам, ибо это не тип данных. Вот выдержка с сайта 1С: «Ссылка — это значение, однозначно характеризующее объекты базы данных (элементы справочников, документы и так далее).

    Для хранения ссылок предназначены типы встроенного языка СправочникСсылка.<имя>, ДокументСсылка.<имя> и так далее.»

    Ссылка — это свойство объекта БД (например, экземпляра справочника Номенклатура). Тип данных этого свойства = СправочникСсылка.<Имя справочника> (например, СправочникСсылка.Номенклатура). То же самое есть в Синтакс-помощнике.

    Так или не так?

    Reply ↓
  27. TSSV

    Добрый день! Про новичков — прежде всего я себя имел ввиду, никого не хотел обидеть, если речь об этом. По поводу остального контента — спасибо, теперь буду знать.

    Reply ↓
  28. Big Fox

    GUID и UUID взаимозаменяемы

    Reply ↓
  29. Adam12345678

    Здравствуйте. Вопрос к знатокам. Если мы перенесли информацию из одной базы в другую, к примеру, номенклатуру с использованием конвертации данных, оставив уникальный идентификатор одинаковым для источника и приёмника, есть ли теоретическая возможность того, что при создании нового элемента в базе приёмнике система сгенерирует уникальный идентификатор такой же как уже имеющийся, перенесенный из другой базы и тем самым «затрет» ранние данные?

    Reply ↓
  30. CheBurator

    (30) ну так сначала, наверное, в базе приемнике ищем СУЩЕСТВУЮЩИЙ элемент, если не нашли — тогда создаем… как здесь что-то может затереть?

    Reply ↓
  31. TSSV

    (30) Нет, этого не может произойти, так как ссылка — кластерный индекс таблицы справочника на уровне СУБД, элемент с существующим в базе УИДом ссылки не будет записан. Можете проверить с помощью конструкции:

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

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

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

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

    НовыйЭлемент.Записать();

    Reply ↓
  32. Adam12345678

    (32) Спасибо.

    Reply ↓

Leave a Comment

Ваш адрес email не будет опубликован. Обязательные поля помечены *