Имя: Пароль:
1C
1С v8
Удаление объекта в узле обмена по обмену данными
0 a2a4
 
27.05.13
17:04
Вот забодался я воевать с оформлением на инфостарте и нет у меня желания ковыряться в вики у мисты, поэтому решил просто кинуть здесь. Ибо если понадобится, то скорее найду в инете, чем в залежах своего компа. Плюс сообщество может подкинуть полезные идеи, что только в плюс.


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

Вариант 1. Использование объекта УдалениеОбъекта. Суть – находим ссылку на объект и по обмену посылаем в удаленную базу. Что-то вроде этого:
Узел = ПланыОбмена.ИмяНужногоПланОбмена.НайтиПоКоду("02");
Ссылка=Справочники.Номенклатура.НайтиПоКоду("000000026");
Удаление = Новый УдалениеОбъекта(Ссылка);
Удаление.Записать();
ПланыОбмена.ЗарегистрироватьИзменения(Узел, Удаление);
Но с данным кодом возникнет следующая проблема – при наличии строки Удаление.Записать(); будет удален объект в текущей базе (а это не нужно). При отсутствии строки Удаление.Записать(); в удаленной базе данные останутся, то есть задача не будет решена.
Вот если в текущей БД нет такого объекта, то можно использовать следующее:
Узел = ПланыОбмена.ИмяНужногоПланОбмена.НайтиПоКоду("02");
Ссылка=Справочники.Номенклатура.ПолучитьСсылку(Новый УникальныйИдентификатор("de18c53b-c3a7-11e2-acf9-001966ee0859"));
Удаление = Новый УдалениеОбъекта(Ссылка);
Удаление.Записать();
ПланыОбмена.ЗарегистрироватьИзменения(Узел, Удаление);
Примечание: в 1С8 следует различать УникальныйИдентификатор (UUID) и глобальный уникальный идентификатор (GUID). При необходимости в сети можно найти код преобразования UUID в GUID и обратно.
В итоге получаем, что данный вариант подходит для случаев когда в удаленном узле необходимо удалить объекты, которые отсутсвуют в текущем узле.
Необходимо учесть ситуацию, что в удаленном узле объект присутствует в других объектах (то есть, удалили номенклатуру «Валенки», а этот элемент присутствует в документах удаленного узла). Тут уже надо думать либо о восстановлении элемента в текущей базе либо предусмотреть замену удаляемого элемента на другой элемент.
 
По варианту с удалением объектов которые отсутствуют в текущей БД весьма подходит http://infostart.ru/public/173851/

Но зачастую требуется удалить объект в удаленной БД, но в текущей БД он должен остаться.
 
Вариант 2. Муторный и не правильный.
Использовать вариант 1, отправить по обмену, получить подтверждение, восстановить элементы и предотвратить отправку восстановленных элементов в удаленный узел.

Вариант 3. Требуется вносить изменения в конфигуратор.
В модуле плана обмена в обработчике ПриОтправкеДанныхПодчиненному и/или ПриОтправкеДанныхГлавному отлавливаем нужные объекты и для них передаём Удаление.
Например:
Процедура ПриОтправкеДанныхПодчиненному(ЭлементДанных, ОтправкаЭлемента, СозданиеНачальногоОбраза)
   Если ЭтоНужныйОбъект Тогда
       ОтправкаЭлемента = ОтправкаЭлементаДанных.Удалить;
   КонецЕсли;
КонецПроцедуры
Примечание: для универсальности возможен такой вариант. В план обмена вводим реквизит ВыполняемыйКод, тип строка неограниченной длины. В этот реквизит оперативно вставляется неоходимый программный код. Опять же следует учесть что процедура ПриОтправкеДанныхПодчиненному и ПриОтправкеДанныхГлавному срабатывает для КАЖДОГО отправляемого элемента.
Процедура ПриОтправкеДанныхПодчиненному(ЭлементДанных, ОтправкаЭлемента, СозданиеНачальногоОбраза)
   Попытка
      Выполнить(ВыполняемыйКод);
   Исключение
   КонецПопытки;
КонецПроцедуры

Вариант 4. Самостоятельно формировать файл XML.
Источник  http://www.cyberforum.ru/1c/thread396358-page4.html
План обмена использую только для регистрации изменений, затем своей обработкой выгружаю выборку в XML по алгоритму из книги Радченко "Практическое пособие разработчика" (довольно просто и гибко получается).
Для передачи удаления объекта не требуется его регистрировать - достаточно выгрузить соответствющую "команду" в XML.
Если Не ВыгружаемыйОбъект.ОтражатьВБухгалтерскомУчете Тогда
   ВыгружаемыйОбъект = Новый УдалениеОбъекта(ВыгружаемыйОбъект.Ссылка);
КонецЕсли;
... и затем собственно сама выгрузка
ЗаписатьXML(ЗаписьXML, ВыгружаемыйОбъект);

________________________________________
А теперь подводные камни.
Если вы желаете удалить некоторый объект, то помните, что на этот объект могут быть завязаны и другие объекты в базе данных. Например – подчиненные справочники, движения документа, независимые регистры сведений и т.д., то есть те объекты которые не имеют смысла при отсутствии удаляемого объекта. Часть объектов можно найти достаточно просто (подчиненные справочники, движения документа, регистры сведений где объект является ведущим измерением), а вот некоторые достаточно проблематично, так как необходимо просматривать каждый объект и смотреть в коде какие изменения он вносит в БД при записи и/или проведении.

И последний совет. Если расхождения в удаленной БД достаточно велики по сравнению с текущей БД, то гораздо быстрее и проще заново создать БД удаленного узла.
1 Kreont
 
27.05.13
17:28
Чуток знакомая ситуация :)

Еще такая идея была обхода: (минус то, что ручная работа, но такие задачи редко нужны постоянно)

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

А уже передать ее в нужную РИБ и автоматом запустить ее одноразово после обмена труда не составит.

И прилеплю еще как удалять при РИБ правильно (это если везде надо удалить а не только в одной БД):
v8: Как правильно удалять элементы справочника если есть РИБ?
Только после взаимных обменов.