Но иногда, при решении практических задач, этих безусловно полезных для формирования правильной «картины мира» у новичка знаний
становится недостаточно…
Про ссылки, 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ах можно прочитать здесь:
Гм. А объекты необъектного типа бывают?
Не путайте помянутых новичков терминологией. Объект может быть переменной объектного типа или экземпляром объектного типа. Но не бывает объектов объектного типа.
(1) vcv, Спасибо за проявленный интерес к публикации и заботу о новичках, которую полностью разделяю.
http://v8.1c.ru/:
Позволю себе цитату с ресурса
«При манипулировании данными, хранящимися в базе данных 1С:Предприятия, зачастую используется объектный подход. Это значит, что обращение (чтение и запись) к некоторой совокупности данных, хранящихся в базе, происходит как к единому целому. Например, используя объектную технику, можно манипулировать данными справочников, документов, планов видов характеристик, планов счетов и т.д.
Характерной особенностью объектного манипулирования данными является то, что на каждый объект, как совокупность данных, существует уникальная ссылка, позволяющая однозначно идентифицировать этот объект в базе данных.
Эта ссылка также хранится в поле базы данных, вместе с остальными данными объекта. Кроме того, ссылка может быть использована как значение какого-либо поля другого объекта. Например, ссылка на объект справочника Контрагенты может быть использована как значение соответствующего реквизита документа ПриходнаяНакладная.»
И все же думаю Вы правы — вместо «объектного типа» здесь лучше использовать формулировку «ссылочного типа» — так будет понятней о чем идет речь.
если честно, я не понял про уникальность… если УИД уникальный в пределах вселенной, т.е. вероятность совпадения невероятно мала, то фактически гарантируется уникальность ссылок в пределах всех информационных баз… это, конечно, если 1С придерживается алгоритма генерации гуида
(3) WKBAPKA, если мы исходим из того, что 1С придерживается (это конечно не документировано), то УИД уникальный в момент его создания, но, мы можем искусственно записать в базу один и тот же УИД в разные объекты разного типа (например, в элемент справочника «Номенклатура» и элемент справочника «Единицы измерения» — такие вещи могут встретиться при добавлении данных с помощью загрузки с использованием КД). И тогда УИД уже не уникален в пределах базы, но ссылки разные, так как ссылка это тип данных плюс УИД.
наверное так оно и есть… с одной стороны… а с другой, интересно, получится ли установить две одинаковые ссылки на один и тот же тип данных…
Замечательная статья. Спасибо Вам за нее
(5) WKBAPKA, нет не получится. в каждой из таблиц базы UUID является ключевым полем. отсюда и невозможность поиметь две номенклатуры с одним UUID
А можно ли подменить UUID конкретного объекта?
(8) Psylocibine, Подменить UUID конкретного объекта можно, но нужно помнить о ссылках на объект — они станут «битыми». Поэтому решение может быть следующим — создаем копию объекта с нужным УИДом, с помощью универсальной обработки «Поиск и замена значений» заменяем ссылки старого объекта на новый, удаляем старый объект. Так же мне приходилось решать задачу перевода метода синхронизации ряда справочников (контрагенты, номенклатура и пр.) с синхронизации по коду на синхронизацию по внутреннему идентификатору в работающей УПП (обмен был с БП) — то есть необходимо было массово заменить УИДы у большого количества элементов. Я поступил следующим образом — сделал полную выгрузку ИБ штатными механизмами УПП — «Выгрузка данных в идентичную конфигурацию» , в сформированном XML файле выгрузки сделал замену GUIDов (предварительно сформировав файл соответствия GUIDов), после чего загрузил переработанный файл выгрузки в пустую базу. Файл выгрузки редактировался как обычный текстовый файл, в каждой строке которого происходил поиск заменяемого GUIDа среди набора подлежащих замене и собственно сама замена. Метод себя оправдал — на операцию ушло несколько часов (не считая подготовки конечно) и в дальнейшем проблем с обменом не возникало.
Хорошая статья. И написана понятным языком.
позновательно
Вотздесь написано иначе
После удаления объект нельзя создать заново. Даже если завести все его реквизиты в соответствии с удаленным объектом, это будет уже другой объект. Для объекта система хранит внутренний идентификатор — ссылку. Ссылка уникальна в пределах всей информационной базы. Двух объектов с одинаковыми ссылками не может существовать на всем протяжении жизни информационной базы. Ссылки удаленных объектов не присваиваются вновь созданным объектам. Система предоставляет возможность хранить в полях базы данных ссылки на объекты базы данных.
При условии, конечно, что вы будете использовать внутренние механизмы для генерации УИДов.
Спасибо, очень помоги, как раз занимался переносом XML нетипизированной партянки и нужно было насильно присваивать ГУИД.
(13) Lo1jke, (10) рад что пригодилось, спасибо за отзывы!
http://infostart.ru/public/192055/
Вот еще на эту тему:
Отличная статья. Как раз кстати. Спасибо
Спаасибо Интересно
Спасибо!
(0)
Это логично, т.к. платформа натыкается на ссылку, получить которую не может, и генерирует на основе неё — ошибку «Объект не найден» с указанием «переработанной» исходной ссылки.
(0)
Вы ничего не развенчали, а еще больше запутали новичков, для которых, якобы, все и «развенчивали».
Вы гарантируете, что после удаления ссылки те данные, на которые она ссылалась — осталось в целости и сохранности? Нет.
Вы гарантируете, что все подчиненные объекты «внутри» удаленного — остались на месте? Нет.
Так называемое «восстановление», да еще и громко названное
— не более чем создание и подгонка новых объектов под старые (битые) ссылки, а не восстановление старых объектов. Старые (и их содержимое) — потеряны навсегда.
А хотите «обмануть» систему — да пожалуйста, не надо ничего изобретать: создаете новый объект, удаляете старую ссылку, заменяете все старые — на новые.
Вуаля, ссылки восстановлены!
Т.е. статья написана «умно», но много воды, напущено тумана (для умности статьи?), и, главное, выводы сделаны совершенно неправильные (или двусмысленные — видимо, сам не разобрался).
(0)
Это сугубо Ваши домыслы.
1С ищет объект по ссылке, а не по «ссылка+тип данных», и что она должна вернуть, если по ссылке — два объекта?
Была теория, что 1С «зашифровала» тип даннных в ссылке, но пока она не получила ни подтверждения, ни полного отпровержения, т.к. ссылки формируются «подряд» (документ — ссылка №1, справочник — ссылка №2, документ — ссылка №3, ссылки по-порядку, последовательно, формируются), однако, и опровержение «зашифрованности» не получено от 1С.
(12) bforce,
Страничка удалена с ИТС.
(0)Tsaregorodtsev,
создавать новую ссылку:
нужно так:
Все.
И не надо тыркать по десять раз ссылку туда-сюда.
(0)Tsaregorodtsev,
Это UUID:
Это GIUD (назван «УИД» в 1С):
А у вас туман один клубится в статье.
Нет штатного средства поиска по GUID в конфиграциях и это очень плохо,под УФ тоже обработок не найти это беда…
(24) pavelyar,
GUID как таковой вообще не используется в платформе 1С. Ссылки хранятся в формате UUID. Что и подтвержадет ошибка «Объект не найден (48:b3e2001617ec3f2a11e1912c787ec129)».
Мне кажется, что «Ссылка — это тип данных,» взрывает мозг новичкам, ибо это не тип данных. Вот выдержка с сайта 1С: «Ссылка — это значение, однозначно характеризующее объекты базы данных (элементы справочников, документы и так далее).
Для хранения ссылок предназначены типы встроенного языка СправочникСсылка.<имя>, ДокументСсылка.<имя> и так далее.»
Ссылка — это свойство объекта БД (например, экземпляра справочника Номенклатура). Тип данных этого свойства = СправочникСсылка.<Имя справочника> (например, СправочникСсылка.Номенклатура). То же самое есть в Синтакс-помощнике.
Так или не так?
Добрый день! Про новичков — прежде всего я себя имел ввиду, никого не хотел обидеть, если речь об этом. По поводу остального контента — спасибо, теперь буду знать.
GUID и UUID взаимозаменяемы
Здравствуйте. Вопрос к знатокам. Если мы перенесли информацию из одной базы в другую, к примеру, номенклатуру с использованием конвертации данных, оставив уникальный идентификатор одинаковым для источника и приёмника, есть ли теоретическая возможность того, что при создании нового элемента в базе приёмнике система сгенерирует уникальный идентификатор такой же как уже имеющийся, перенесенный из другой базы и тем самым «затрет» ранние данные?
(30) ну так сначала, наверное, в базе приемнике ищем СУЩЕСТВУЮЩИЙ элемент, если не нашли — тогда создаем… как здесь что-то может затереть?
(30) Нет, этого не может произойти, так как ссылка — кластерный индекс таблицы справочника на уровне СУБД, элемент с существующим в базе УИДом ссылки не будет записан. Можете проверить с помощью конструкции:
УИД = Новый УникальныйИдентификатор(ЗаданныйУИД);
НоваяСсылка = Справочники[ИмяМетаданных].ПолучитьСсылку(УИД);
НовыйЭлемент = Справочники[ИмяМетаданных].СоздатьЭлемент();
НовыйЭлемент.УстановитьСсылкуНового(НоваяСсылка);
НовыйЭлемент.Записать();
(32) Спасибо.