Приветствую Вас ГостьСреда, 15.05.2024, 08:55

Каталог статей


План обмена

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

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

К механизмам обмена данными могут быть отнесены:

  • Планы обмена,
  • XML-сериализация,
  • Средства чтения и записи документов XML.

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

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

XML-сериализация позволяет преобразовать объект «1С:Предприятия» в последовательность данных, представленных в формате XML. Кроме этого, XML-сериализация выполняет и обратное преобразование – преобразует последовательность данных формата XML в объект «1С:Предприятия», при условии что имеется соответствующий тип «1С:Предприятия».

Состав объектов, участвующих в плане обмена, определяется с помощью кнопки "Состав" на вкладке "Основные"

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

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

При записи и удалении объектов обмена план обмена формирует записи регистрации изменений. Записи регистрации изменений хранятся в таблицах регистрации изменений, причем для каждого объекта обмена ведется своя таблица.

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

Сообщение с точки зрения плана обмена – это единица обмена информацией.

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

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

Так же надо предусмотреть ситуацию, когда одна и та же запись одновременно будет изменена в нескольких базах. В этом случае надо принять решение о том, какие изменения будут приоритетными. Решением для этой проблемы может быть добавление реквизита Главный типа Булево для плана обмена. При наличии коллизий, будем определять приоритет изменений по заполненному значению этого реквизита.

Перед тем как начать обмен данными, надо сформировать список изменений. В первый раз это надо сделать для всех данных. Для этого используется метод ПланыОбмена.ЗарегистрироватьИзменения(Узел), где Узел - это узел обмена базы получателя. В результате выполнения этого метода будут сформированы записи изменений для всех объектов данных и им назначен получатель.

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

Элементы.ФормаЗарегистрироватьИзменения.Доступность = НЕ ПредопределенныйУзел(Элементы.Список.ТекущаяСтрока);

 где ФормаЗарегистрироватьИзменения - кнопка назначенная для выполнения команды

ПредопределенныйУзел - это функция, выполняемая на сервере без контекста. Выполнение без контекста предпочтительно тем, что внеконтекстная процедура выполняется на сервере значительно быстрее за счет того, что на сервер с клиента не передается весь контекст формы.

 &НаСервереБезКонтекста
Функция ПредопределенныйУзел(Узел)
    Возврат Узел = ПланыОбмена.Филиалы.ЭтотУзел();
КонецФункции

Запускать процедуру обмена будем в обработке. На форме обработки добавим команду:

&НаКлиенте
Процедура ВыполнитьОбмен(Команда)
    ВыполнитьОбменНаСервере();
КонецПроцедуры

&НаСервереБезКонтекста
Процедура ВыполнитьОбменНаСервере()
    ВыборкаУзлов = ПланыОбмена.Филиалы.Выбрать();
    Пока ВыборкаУзлов.Следующий() Цикл
        Если ВыборкаУзлов.Ссылка <> ПланыОбмена.Филиалы.ЭтотУзел() Тогда
            УзелОбъект = ВыборкаУзлов.ПолучитьОбъект();
            УзелОбъект.ПрочитатьСообщениеСИзменениями();
            УзелОбъект.ЗаписатьСообщениеСИзменениями();            
        КонецЕсли;
    КонецЦикла;
КонецПроцедуры

Мы получаем выборку узлов обмена, обходим её в цикле и запускаем процедуру чтения  из сообщений и записи изменений в сообщения.

Методы ПрочитатьСообщениеСИзменениями и ЗаписатьСообщениеСИзменениями это экспортные процедуры в модуле объекта плана обмена:

Процедура ЗаписатьСообщениеСИзменениями()  Экспорт

    Сообщение = Новый СообщениеПользователю;
    Сообщение.Текст = "-------- Выгрузка в узел " + Строка(ЭтотОбъект) + " ------------";
    Сообщение.Сообщить();
    Каталог = КаталогВременныхФайлов();
    
    // Сформировать имя временного файла.    
    ИмяФайла = Каталог + ?(Прав(Каталог,1) = "\","","\") + "Message" + СокрЛП(ПланыОбмена.Филиалы.ЭтотУзел().Код) + "_" + СокрЛП(ссылка.Код) + ".xml";
    
    // Создать объект записи XML
    // *** ЗаписьXML-документов.    
    ЗаписьXML = Новый ЗаписьXML;
    ЗаписьXML.ОткрытьФайл(ИмяФайла);
    ЗаписьXML.ЗаписатьОбъявлениеXML();     
    
    // *** Инфраструктура сообщений.       
    ЗаписьСообщения = ПланыОбмена.СоздатьЗаписьСообщения();
    ЗаписьСообщения.НачатьЗапись(ЗаписьXML, Ссылка);

    Сообщение = Новый СообщениеПользователю;
    Сообщение.Текст = " Номер сообщения: " + ЗаписьСообщения.НомерСообщения;
    Сообщение.Сообщить();   
    
    // Получить выборку измененных данных
    // *** Механизм регистрации изменений.
    ВыборкаИзменений = ПланыОбмена.ВыбратьИзменения(ЗаписьСообщения.Получатель,ЗаписьСообщения.НомерСообщения);    
    
    Пока ВыборкаИзменений.Следующий() Цикл
        ЗаписатьXML(ЗаписьXML, ВыборкаИзменений.Получить());
    КонецЦикла;
    
    ЗаписьСообщения.ЗакончитьЗапись();

    ЗаписьXML.Закрыть();
    
    Сообщение = Новый СообщениеПользователю;
    Сообщение.Текст = ИмяФайла + Символы.ПС + "-------- Конец выгрузки ------------";
    Сообщение.Сообщить();  
    
КонецПроцедуры

Пояснения:

ПланыОбмена.ВыбратьИзменения(ЗаписьСообщения.Получатель,ЗаписьСообщения.НомерСообщения) - Формирует выборку измененные данные для передачи их в тот или иной узел плана обмена.

Первый параметр - получатель (узел), для передачи в который отбираются изменения. 

Второй параметр - номер сообщения. При создании объекта ЗаписьСообщения он формируется автоматически.

ЗаписатьXML(ЗаписьXML, ВыборкаИзменений.Получить());

ВыборкаИзменений.Получить() - получает объект (например тип СправочникОбъект), который был изменен

ЗаписатьXML() - сериализует объект. На выходе получается Запись XML , например для записи справочника Клиенты:

<CatalogObject.Клиенты>
    <Ref>d1de2391-9575-11ec-910a-00d861b61c8f</Ref>
    <DeletionMark>false</DeletionMark>
    <Code>ФЛ000000001</Code>
    <Description>Пушкин Александр Сергеевич</Description>
</CatalogObject.Клиенты>

 

////////////////////////////////////////////////////////////////////////////////////////////////////

Процедура ПрочитатьСообщениеСИзменениями() Экспорт
    
    Каталог = КаталогВременныхФайлов();
    
    // Сформировать имя временного файла.    
    ИмяФайла = Каталог + ?(Прав(Каталог,1) = "\","","\") + "Message"  + СокрЛП(ссылка.Код) + "_" + СокрЛП(ПланыОбмена.Филиалы.ЭтотУзел().Код) + ".xml";        
    
    Файл = Новый Файл(ИмяФайла);
    Если Не Файл.Существует() Тогда
        Возврат;
    КонецЕсли;
    
    // *** Чтение документов XML       
    // Попытаться открыть файл.    
    ЧтениеXML = Новый ЧтениеXML();
    Попытка    
        ЧтениеXML.ОткрытьФайл(ИмяФайла);    
    Исключение                          
        Сообщение = Новый СообщениеПользователю;
        Сообщение.Текст = "Невозможно открыть файл обмена";
        Сообщение.Сообщить();
        Возврат;                        
    КонецПопытки;
    
    Сообщение = Новый СообщениеПользователю;
    Сообщение.Текст =  "-------- Загрузка из " + Строка(ЭтотОбъект) + " ------------";
    Сообщение.Сообщить();
    
    Сообщение = Новый СообщениеПользователю;
    Сообщение.Текст =  " – Считывается файл " + ИмяФайла;;
    Сообщение.Сообщить();     
    
    // Загрузить из найденного файла
    // *** Инфраструктура сообщений.    
    ЧтениеСообщения = ПланыОбмена.СоздатьЧтениеСообщения();
    
    // Читать заголовок сообщения обмена данными – файла XML.    
    ЧтениеСообщения.НачатьЧтение(ЧтениеXML);            
    
    // Сообщение предназначено не для этого узла.

    Если ЧтениеСообщения.Отправитель <> Ссылка Тогда    
        ЧтениеСообщения.ЗакончитьЧтение();
        ВызватьИсключение "Неверный узел";
    КонецЕсли;
    
    // Удаляем регистрацию изменений для узла отправителя сообщения.
    // *** Служба регистрации изменений.
    ПланыОбмена.УдалитьРегистрациюИзменений(ЧтениеСообщения.Отправитель, ЧтениеСообщения.НомерПринятого);      
    
    // Читаем данные из сообщения *** XML-сериализация.
    Пока ВозможностьЧтенияXML(ЧтениеXML) Цикл
        //Читаем очерадное значение 
        Данные = ПрочитатьXML(ЧтениеXML);
        
        // Не переносим изменение, полученное в главный из неглавного, если есть регистрация изменения.
        Если Не ЧтениеСообщения.Отправитель.Главный И ПланыОбмена.ИзменениеЗарегистрировано(ЧтениеСообщения.Отправитель, Данные) Тогда
            Сообщение = Новый СообщениеПользователю;
            Сообщение.Текст = " – Изменения отклонены";
            Сообщение.Сообщить(); 
            Продолжить;
        КонецЕсли;   
        
        Данные.ОбменДанными.Отправитель = ЧтениеСообщения.Отправитель;
        Данные.ОбменДанными.Загрузка = Истина;
        Данные.Записать();
                
    КонецЦикла;
    
    ЧтениеСообщения.ЗакончитьЧтение();    
    ЧтениеXML.Закрыть();
    УдалитьФайлы(ИмяФайла);  
    
    Сообщение = Новый СообщениеПользователю;
    Сообщение.Текст =  "-------- Конец загрузки ------------";
    Сообщение.Сообщить();
    
КонецПроцедуры

Пояснения:

Если ЧтениеСообщения.Отправитель <> Ссылка Тогда... - идет проверка на загрузку данных от нужного узла. Мы перебираем узлы из выборки по узлам и загружаем только те данные, которые адресованы именно тому узлу, который мы обрабатываем в выборке.

ПланыОбмена.УдалитьРегистрациюИзменений(ЧтениеСообщения.Отправитель, ЧтениеСообщения.НомерПринятого) - удаляет записи регистрации изменений 

Если Не ЧтениеСообщения.Отправитель.Главный И ПланыОбмена.ИзменениеЗарегистрировано(ЧтениеСообщения.Отправитель, Данные) Тогда...

ПланыОбмена.ИзменениеЗарегистрировано(ЧтениеСообщения.Отправитель, Данные) - возвращает Истина, если для данного объекта в текущем узле плана обмена зафиксированы изменения

Если пришли изменения по объекту и этот объект был изменен в текущей базе, то проверяем реквизит "Главный" для плана обмена. Если отправитель определен как Главный, то вносим изменения, иначе выводим сообщение и вызываем исключение.

ВозможностьЧтенияXML(ЧтениеXML) - аналог метода Следующий для выборки

ПрочитатьXML(ЧтениеXML) - десериализует запись XML в объект данных. В базе должен быть объект с таким же названием иструктурой.

Данные.ОбменДанными.Отправитель = ЧтениеСообщения.Отправитель - пока непонятно зачем...

Распределенная информационная база

Если у плана обмена установлено свойство "Распределенная информационная база", то для данного плана обмена включается механизм распределенных информационных баз.

Распределенная информационная база должна иметь четко определенную древовидную структуру. Количество уровней в такой структуре не ограничено, главное – между двумя связанными узлами всегда должно быть определено отношение «главный – подчиненный»

Конфигурация может быть изменена только в узле, не имеющем главного узла (то есть в корневом). Изменения данных могут выполняться в любом узле.

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

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

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

Механизм распределенных информационных баз в списке узлов плана обмена автоматически создает 3 команды:

  • Создать начальный образ
  • Прочитать изменения
  • Записать изменения

 Создание начального образа рекомендуется. Пи выполнении этой команды формируется файл информационной базы 1Cv8.1CD. Если используется файловая 1С, то этот файл надо положить в каталог новой базы. При загрузке конфигуратора новой базы, в базе будут все объекты и база будет защищенной от изменений средствами управления распределенной информационной базой.

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

Если в присланных изменениях есть изменения в конфигурации и данных, то порядок принятия изменений будет следующим:

Сначала будет изменена основная конфигурация и выдано сообщение о необходимости выполнения обновления конфигурации базы данных, но самих данных, мы пока не увидим.

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

Программная реализация обмена РИБ

При желании стандартные команды обмена РИБ можно описать программно.

Для примера создадим обработку, на которой будет один реквизит ПолеВводаОтделение типа ПланОбмена с РИБ и 3 команды.

Реализация команд:

Создать начальный образ

&НаКлиенте
Процедура СоздатьНачальныйОбраз(Команда)
    Диалог = Новый ДиалогВыбораФайла(РежимДиалогаВыбораФайла.ВыборКаталога);
    Диалог.Заголовок = "Укажите каталог информационной базы:";
    Если Диалог.Выбрать() Тогда
        СоздатьНачальныйОбразНаСервере(ПолеВводаОтделение, Диалог.Каталог);
        Сообщение = Новый СообщениеПользователю;
        Сообщение.Текст = "Создание начального образа узла завершено.";
        Сообщение.Сообщить();
    КонецЕсли;
КонецПроцедуры

&НаСервереБезКонтекста
Процедура СоздатьНачальныйОбразНаСервере(Узел, КаталогСоединения)
    ПланыОбмена.СоздатьНачальныйОбраз(Узел, "File =""" + КаталогСоединения + """");
КонецПроцедуры

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

Записать изменения

&НаКлиенте
Процедура ЗаписатьИзменения(Команда)
    Диалог = Новый ДиалогВыбораФайла(РежимДиалогаВыбораФайла.Сохранение);
    Диалог.Заголовок = "Укажите файл обмена:";
    Если Диалог.Выбрать() Тогда
        ЗаписатьИзмененияНаСервере(ПолеВводаОтделение, Диалог.ПолноеИмяФайла);
        Сообщение = Новый СообщениеПользователю;
        Сообщение.Текст = "Запись изменений завершена.";
        Сообщение.Сообщить();
    КонецЕсли;
КонецПроцедуры

&НаСервереБезКонтекста
Процедура ЗаписатьИзмененияНаСервере(Узел, ИмяФайла)
    // Создать и проинициализировать объект ЗаписьXML.
    ЗаписьXML = Новый ЗаписьXML;
    ЗаписьXML.ОткрытьФайл(ИмяФайла);
    
    // Создать объект ЗаписьСообщенияОбмена и начать запись сообщения.
    ЗаписьСообщения = ПланыОбмена.СоздатьЗаписьСообщения();
    ЗаписьСообщения.НачатьЗапись(ЗаписьXML, Узел);
    
    // Записать содержимое тела сообщения обмена данными распределенной ИБ.
    ПланыОбмена.ЗаписатьИзменения(ЗаписьСообщения);             
    
    // Закончить запись сообщения и запись XML.
    ЗаписьСообщения.ЗакончитьЗапись();
    ЗаписьXML.Закрыть();
КонецПроцедуры
 

метод «ЗаписатьИзменения()» позволяет задать максимальное число элементов данных, которые помещаются в сообщение в рамках одной транзакции базы данных. По умолчанию все данные помещаются в сообщение в рамках одной транзакции. Такой режим является рекомендуемым, так как гарантирует согласованность данных, помещаемых в сообщение.

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

Прочитать изменения

&НаКлиенте
Процедура ПрочитатьИзменения(Команда)
    Диалог = Новый ДиалогВыбораФайла(РежимДиалогаВыбораФайла.Открытие);
    Диалог.Заголовок = "Укажите файл обмена:";
    Если Диалог.Выбрать() Тогда           
        
        ПрочитатьИзмененияНаСервере(Диалог.ПолноеИмяФайла);
        
        Сообщение = Новый СообщениеПользователю;
        Сообщение.Текст = "Чтение изменений завершено.";
        Сообщение.Сообщить();             
        
    КонецЕсли;
КонецПроцедуры

&НаСервереБезКонтекста
Процедура ПрочитатьИзмененияНаСервере(ИмяФайла)
    // Создать и проинициализировать объект ЧтениеXML.
    ЧтениеXML = Новый ЧтениеXML;
    ЧтениеXML.ОткрытьФайл(ИмяФайла);
    
    // Создать объект ЧтениеСообщенияОбмена и начать чтение сообщения.
    ЧтениеСообщения = ПланыОбмена.СоздатьЧтениеСообщения();
    ЧтениеСообщения.НачатьЧтение(ЧтениеXML);
    
    // Прочитать содержимое тела сообщения.
    ПланыОбмена.ПрочитатьИзменения(ЧтениеСообщения);
    
    // Закончить чтение сообщения и чтение XML.
    ЧтениеСообщения.ЗакончитьЧтение();
    ЧтениеXML.Закрыть();
КонецПроцедуры
 


Механизм распределенных информационных баз содержит программное средство реконфигурирования структуры узлов распределенной базы. Метод ПланыОбменаМенеджер.УстановитьГлавныйУзел() позволяет как исключить узел или целую ветвь из дерева, так и включить узел в дерево или изменить подчиненность в дереве.

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

1. Изменение подчиненности в дереве: подчиненный узел 2 делаем главным для узла 1

Команды:

// В информационной базе Узла2.
ПланыОбменаМенеджер.УстановитьГлавныйУзел(Неопределено);

// В информационной базе Узла1.
ПланыОбменаМенеджер.УстановитьГлавныйУзел(Узел2);

Будут удалены все записи регистрации изменений конфигурации Узла1, относящиеся к Узлу2. Записи регистрации изменения данных удалены не будут, так как передача изменений данных будет по-прежнему возможна между этими узлами.

2. Отключить от дерева ветвь

Команды:

// В информационной базе Узла1.
ПланыОбменаМенеджер.УстановитьГлавныйУзел(Неопределено);

3. Создать РИБ из отбельных баз с одинаковой структурой

Команды:

// В информационных базах Узла2, Узла3 и Узла4.
ПланыОбменаМенеджер.УстановитьГлавныйУзел(Узел1);

Обмен предопределенными данными

Допустим справочник Склады содержит предопределенный элемент с именем Основной.

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

В нашем случае при открытии списка складов в базе филиала будет автоматически создан элемент справочника Склады, связанный с предопределенным элементом справочника с именем Основной. При этом свойство этого элемента справочника ИмяПредопределенныхДанных будет установлено в значение Основной

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

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

В Распределенных Информационных Базах проблем с переносов предопределенных данных нет.

Объекты встроенного языка для работы с планами обмена

ЗаписьСообщенияОбмена – объект предназначен для организации записи сообщения обмена данными.

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

Категория: Объекты конфигурации и типы данных | Добавил: leshic (25.02.2022)
Просмотров: 594 | Рейтинг: 0.0/0
Всего комментариев: 0
Имя *:
Email *:
Код *:
Вход на сайт
Поиск
Категории раздела
СКД [48]
Регистры [7]
Формы [41]
Администрирование [35]
Запросы [10]
Объекты конфигурации и типы данных [20]
Взаимодействие с другими базами, приложениями и источниками данных [16]
Программирование [29]
Статистика

Онлайн всего: 1
Гостей: 1
Пользователей: 0