Библиотеки разработки

Сообщения и их свойства

Тип Сообщение

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

Предусловие: создана в процессе переменная типа Сообщение с именем ВхСообщ.

Свойства типа:

  • Id - string;

  • CorrelationId - string;

  • CreationDate - DateTime (utc);

  • Properties;

  • IsArray - является ли тело сообщения массивом;

  • OriginalSystemDataType (string, get-only);

  • StreamId (Guid, get-only) - идентификатор цепочки запросов;

  • BodyLength (int, get-only) - размер тела сообщения в байтах;

  • HasBinaryInQueue (bool, get-only) - есть ли бинарные данные в очереди;

  • IsBinaryLoadedOrSet (bool, get-only) - загружены ли бинарные данные;

  • IsNewBinary (bool, get-only) - бинарные данные были установлены пользователем.

Получить все свойства сообщения:

Logger.Info("Свойства"); //получить все свойства сообщения Списком
foreach (var prop in InitMessage.Properties.GetPropertiesList())
{
        Logger.Info(prop);
}
Logger.Info("Свойства GetProperties()"); //получить все свойства сообщения Словарем
foreach (var propKey in InitMessage.Properties.GetProperties().Keys)
{
        Logger.Info(propKey);
}

Скопировать все свойства сообщения другому сообщению:

mes.Properties.CopyFrom(InitMessage.Properties);

DataType

Guid GetDataTypeId()
bool HasDataType()
void SetDataTypeId(Guid value)
bool TrySetDataTypeId(Guid value)

//генерируемые

Types.DataTypes GetDataType() - возвращает значение Types.DataTypes в соответствии с
DataType сообщения.
если DataType, указанного в сообщении, нет или он не заполнен, то возвращает
Types.DataTypes.Empty
bool SetDataType(Types.DataTypes value) - устанавливает в DataType значение в соответствии
с value.
если value = 0, то очищает DataType и возвращает true. Если такого DataType нет, то
возвращает false
Types.Classifiers GetClassifier() - возвращает enum, соответствующий полю dataTypeId из
конфигурации классификатора.

SystemDataType

Guid GetSystemDataTypeId()
bool HasSystemDataType()
void SetSystemDataTypeId(Guid value)
bool TrySetSystemDataTypeId(Guid value)

//генерируемые

Types.SM GetSystemDataType() - возвращает значение Types.SM в соответствии с
SystemDataType сообщения.
если SystemDataType, указанного в сообщении, нет или он не заполнен, то возвращает
Types.SM.Empty
bool SetSystemDataType(Types.SM value) - устанавливает в SystemDataType значение в
соответствии с value.
если value = 0, то очищает SystemDataType и возвращает true. Если такого SystemDataType
нет, то возвращает false

Source

Guid GetSourceId()

//генерируемые

Cluster.Systems GetSource() - возвращает систему из поля Source.
Если Source - не система, то возвращает Cluster.Systems.Empty

Receivers

OwnList<Module> GetReceiversList()
void SetReceivers(OwnList<Module> receivers)
void AddReceiver(Guid receiver)
void RemoveReceiver(Guid id)

//генерируемые

OwnList<Cluster.Systems> GetReceivers() - перебирает получателей и возвращает только
получателей-систем
bool AddReceiver(Cluster.Systems system) - добавляет в список получателя.
Если такой получатель уже есть - возвращает true.
Если такого получателя нет или system==0, то ничего не делает и возвращает false
bool AddReceivers(OwnList<Cluster.Systems> systems) - добавляет в список получателей.
Если хотя бы одного получателя нет или system==0, то ничего не делает и возвращает false.
Если есть дубликаты - второй раз не добавляем.
bool RemoveReceiver(Systems system) - удаляет получателя.
Если такого получателя нет в списке в сообщении, то возвращает true.
Если system не существует или system==0, то возвращает false
bool ClearReceivers() - очищает всех получателей

Обработчики

Для получения сведений об обработчике сообщения используется метод:

Metadata.Handlers GetHandler()

Body

Преобразования тела сообщения в маппинге и алгоритме

Неявные преобразования Сообщение.Body (при использовании маппинга без выражений) в: - String (Массив = false) - неявно вызывается метод GetBodyAsString(); - Тип данных, Сложный тип - неявно вызывается метод GetBodyAsObject(). Явные преобразования «Сообщение» в Тип данных:

byte[] GetBodyAsBytes() //получить тело сообщения как массив байт
string ВхСообщ.GetBodyAsString() // получить тело в типе строка
JObject ВхСообщ.GetBodyAsObject() // получить тело сообщения как объект
// если в теле передан массив из одного элемента вернет этот элемент как объект типа
object ВхСообщ.GetBodyAsObject(Type t) // получить тело сообщения как объект
// если в теле передан массив из одного элемента вернет этот элемент как объект типа
T ВхСообщ.CastToDataType<T>() //получить тело сообщения как объект типа.
// если в теле передан массив из одного элемента вернет этот элемент как объект типа
T ВхСообщ.CastToDataType<T>(int index) //получить тело сообщения как объект типа.
// если в теле передан не массив и index == 0 вернет этот элемент как объект типа
// если в теле передан массив и index < длины массива вер нет элемент по индексу как
объект типа
BaseClass ВхСообщ.GetBodyAsDataType() //получить сообщение как объект типа
установленного в DataType
//Если DataType не задан - вернет null
BaseClass ВхСообщ.GetBodyAsSystemDataType() //получить сообщение как объект типа
установленного в SystemDataType
//Если SystemDataTypeне задан - вернет null

Примеры использования в алгоритме

// Тип - Тип данных
Тип Тип1 = new Тип();
Тип1 = (Тип)ВхСообщ.GetBodyAsObject(typeof(Тип));
43
Тип Тип2 = new Тип();
Тип2 = ВхСообщ.CastToDataType<Тип>();
Тип Тип3 = new Тип();
Тип3 = ВхСообщ.GetBodyAsObject().ToObject<Тип>();
Тип Тип4 = new Тип();
Тип4 = ВхСообщ.CastToDataType<Тип>(3);
BaseClass body = Вх.GetBodyAsDataType();
switch(body)
{
case Человек par:
Logger.Debug(par.Имя);
break;
case Адрес par:
Logger.Debug(par.Город);
break;
case null:
Logger.Debug("Это нулл");
break;
default:
break;
}

Другие методы

ВхСообщ.SetBody(object value) // задать тело как объект
ВхСообщ.SetBody(string obj) // задать тело сообщения из строки
void CopyBody(Message other) // позволяет скопировать тело из одного сообщения в другое
Копирование полное
bool ВхСообщ.HasBody(); // вернет false, если тело сообщения пустое или длина = 0 байт
bool ВхСообщ.SetBody(Message message) - Копирует тело сообщения, DataType и SystemDataType

Работа с массивами в теле сообщения

JArray ВхСообщ.GetBodyAsArrayOfObjects(); // возвращает массив Объектов. Работает даже если в теле один объект
int ВхСообщ.BodyArrayCount(); // возвращает количество элементов в массиве, иначе -1
bool ВхСообщ.BodyIsArray(); // проверяет есть ли внутри массив
void ВхСообщ.GetBodyAsArrayOfObjects<T>(OwnList<T> list); //заполняет переданный массив данными из тела
OwnList<BaseClass> ВхСообщ.GetBodyAsArrayOfDataTypes() //получить сообщение как массив объектов типа установленного в DataType
//Если DataType не задан - вернет null
OwnList<BaseClass> ВхСообщ.GetBodyAsArrayOfSystemDataTypes() //получить сообщение как массив объектов типа установленного в SystemDataType
//Если SystemDataType не задан - вернет null

Properties

Сообщение может содержать пользовательские и системные свойства. Для работы с системными свойствами рекомендуется использовать перечисление MessageProperties со значениями:

  • OriginalFileName;

  • AnswerDataType;

  • AnswerSystemDataType;

  • AnswerRequired;

  • MethodType;

  • HandlerId;

  • ResponseCode: задает код ответа, возвращаемый внешней системе. Особенности обработки кодов ответа зависят от используемой внешней системы и описаны в соответствующих разделах: Расширенное REST API и Веб-сервис.

  • ResponseMessage;

  • MessageType24;

  • IsTracking;

  • Format;

  • Trigger.

    Пример SetProperty для системных свойств:

    InitMessage.SetProperty(MessageProperties.ResponseCode, 400);
    InitMessage.SetProperty(MessageProperties.ResponseMessage, "resp test");
    

Поддерживаемые типы свойств:

  • int;

  • string;

  • decimal;

  • bool;

  • Guid;

  • DateTime.

Важно

Во все методы вместо string name можно передавать значение перечисления.

//добавить свойство если такого нет
void AddProperty<T>(string name, T value)
void AddListProperty<T>(string name, OwnList<T> value)
void AddIntProperty(string name, int value)
void AddIntProperty(string name, int? value)
void AddIntListProperty(string name, OwnList<int?> value)
void AddIntListProperty(string name, OwnList<int> value)
// Установка значений
void SetProperty<T>(string name, T value)
void SetListProperty<T>(string name, OwnList<T> value)
void SetIntProperty(string name, int? value)
void SetIntProperty(string name, int value)
void SetIntListProperty(string name, OwnList<int?> value)
void SetIntListProperty(string name, OwnList<int> value)
//получение свойств
T GetProperty<T>(string name)
bool TryGetProperty<T>(string name, out T value)
bool TryGetProperty<T>(string name, out T value, T ifNullDefault)
OwnList<T> GetListProperty<T>(string name)
bool TryGetListProperty<T>(string name, out OwnList<T> values)
int GetIntProperty(string name)
int GetIntProperty(string name, int defaultIfNull)
int? GetIntOrNullProperty(string name)
bool TryGetIntProperty(string name, out int value)
bool TryGetIntProperty(string name, out int? value, int defaultIfNull) => TryGetProperty(name,
out value, defaultIfNull);
bool TryGetIntOrNullProperty(string name, out int? value) => TryGetProperty(name, out value);
OwnList<int> GetIntListProperty(string name)
OwnList<int?> GetIntOrNullListProperty(string name)
bool TryGetIntListProperty(string name, out OwnList<int> value)
bool TryGetIntOrNullListProperty(string name, out OwnList<int?> value)
//прочие методы
Type GetPropertyType(string name)
bool HasProperty(string name)
bool HasProperty<T>(string name)
bool HasListProperty<T>(string name)
bool IsNullProperty(string name)
bool HasIntProperty(string name);
bool HasIntNullProperty(string name);
bool HasIntListProperty(string name);
//Удаление свойств
Remove(string name) //удаляет свойство из коллекции*

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

InitSource
InitProperties
InitDataType
InitExternalType

Пример:

В шаге Установка переменных есть возможность выполнять маппинг следующего типа:

  • из сообщения в переменную тип «метаданные- типы данных» с настройками маппинга «InitDataType»

  • из сообщения в переменную тип «метаданные- системы» с настройками маппинга «InitSource»

  • из сообщения в переменную тип «метаданные- Метаданные систем» с настройками маппинга «InitExternalType»

  • из сообщения в переменную тип «метаданные- Коллекция свойств» с настройками маппинга «InitProperties»

Логирование

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

Для записи в лог реализован фасад Logger. Методы для записи в лог:

  • Verbose (string textMessage)

  • Debug (string textMessage)

  • Info (string textMessage)

  • Warning (string textMessage)

  • Error (string textMessage)

  • Fatal (string textMessage)

Переданный текст регистрируется в лог того модуля, в котором непосредственно исполняется код. Для лога устанавливается функциональность Custom.

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

Методы фасада Logger

//Оперативные журналы
MessageLoggingEventCollection GetOperativeJournal(Guid moduleId, OperativeJournalFilter
filter);
MessageLoggingEventCollection GetOperativeJournal(Guid moduleId,
                long? minId,
                long? maxId,
                int count = 100,
                DatereonLogLevel level = DatereonLogLevel.Verbose,
                string[] features = null,
                string[] loggerName = null);

//Оперативные события
MessageEventCollection GetOperativeEvents(Guid moduleId, EventsFilter filter);
MessageEventCollection GetOperativeEvents(Guid moduleId,
                long? minId,
                long? maxId,
                DateTime? start,
                DateTime? end,
                Guid? messageId,
                Guid? processId,
                Guid? streamId,
                Guid? initialSourceId,
                Guid? dataTypeId,
                MessageEventType[] eventTypes,
                string[] operations,
                int count = 100,
                IssueLevel level = IssueLevel.Verbose);

//Архивные журналы
List<HistoryLoggingEvent> GetHistoryJournal(Guid moduleId, HistoryLogFilter filter);
List<HistoryLoggingEvent> GetHistoryJournal(Guid moduleId,
                DateTime? start,
                DateTime? end,
                string queryText,
                DatereonLogLevel Level = DatereonLogLevel.Debug,
                int count = 200,
                string[] features = null,
                string[] loggerNames = null);

//Архивные события
List<HistoryEvent> GetHistoryEvents(Guid moduleId, EventsFilter filter);
List<HistoryEvent> GetHistoryEvents(Guid moduleId,
                DateTime? start,
                DateTime? end,
                Guid? messageId,
                Guid? processId,
                Guid? streamId,
                Guid? initialSourceId,
                Guid? dataTypeId,
                string level,
                string queryText,
                MessageEventType[] eventTypes,
                string[] operations,
                int count = 200);

Для работы с методами реализованы вспомогательные классы:

OperativeJournalFilter - параметры фильтрации данных оперативного журнала

public long MinId = -1;
public long MaxId = -1;
public int Count = 100;
public DatereonLogLevel Level = DatereonLogLevel.Debug;
public string[] Features
public string[] LoggerNames

HistoryLogFilter - параметры фильтрации данных архивного журнала

public DateTime Start
public DateTime End
public int PageSize = 200;
public string Logger
public bool OrderAsc
public string[] LoggersNames

/// Набор логгеров для поиска
public string[] PositiveLoggersNames;

/// Набор логгеров для исключения
public string[] NegativeLoggersNames;
public string QueryText
public DatereonLogLevel MinLogLevel
public LoggingFeature[] Features
private string[] _featuresAsString;
public HashSet<LoggingFeature> FeatureInclude ;
public HashSet<LoggingFeature> FeatureExclude ;
public string[] FeaturesAsString

EventsFilter - параметры фильтрации событий

public DateTime Start
public DateTime End
public int PageSize = 200;
public Guid? DataTypeId
public Guid? MessageId
public Guid? ProcessId
public Guid? StreamId
public Guid? InitialSourceId
public IssueLevel IssueLevel
public MessageEventType[] EventTypes
public string[] MessageTypes
public long? MaxId
public long? MinId
public string MinLevel
public string QueryText
public bool OrderAsc
public bool OperativeOnly

HistoryLoggingEvent - запись журнала

public DatereonLogLevel Level

/// Временная метка
public DateTime TimeStamp

/// Фича
public LoggingFeature Feature

/// Имя логера-источника
public string LoggerName

/// Событие
public string Message

/// Номер события
public long EventNumber

HistoryEvent - событие

public DateTime TimeStamp

/// Порядковый номер события
public long EventNumber

/// Тип события
public MessageEventType EventType

/// Имя источника события

public string EventSource

/// Дополнительные сведения о событии
public string EventDetails

/// Копия сообщения (без тела)
public InternalMessage Message

/// Размер тела сообщения

public int MessageBodyLength
public IssueLevel LogLevel

/// ИД модуля, по инициативе которого произошло событие
public Guid TargetId

MessageLoggingEventCollection - набор записей журнала

/// Ключ = идентификатору запущенного процесса
public int Key

/// Список событий логирования
public List<MessageLoggingEvent> Events;
public int? ServiceState
public string ServiceStateMessage

MessageEventCollection - набор событий

/// Ключ = идентификатору запущенного процесса
public int Key

/// Список событий логирования
public List<MessageEvent> Events;
public int? ServiceState
public string ServiceStateMessage

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

Работа со ссылками

Поле или переменная типа Ссылка представляет собой класс LinkType, внутри которого присутствуют 2 поля:

public class LinkType
: BaseClass
{
public Guid? EntityId { get; set; } // идентификатор объекта, на который мы ссылаемся
public Guid? DataTypeId { get; set; } // идентификатор типа данных объекта, на который мы ссылаемся
}

Для работы со ссылками доступны следующие методы:

//ПолеСсылки - переменная типа Ссылка

ПолеСсылки.IsEmpty(); // вернет true, если EntityId == null && DataTypeId == null

ПолеСсылки.IsNullEntityId(); // вернет true, если EntityId == null
ПолеСсылки.IsNullDataTypeId(); // вернет true, если DataTypeId == null

ПолеСсылки.GetEntityId(); // вернет EntityId если он заполнен, иначе выкинет исключение
ПолеСсылки.GetDataTypeId()); // вернет DataTypeId он заполнен, иначе выкинет исключение8

ПолеСсылки.TryGetEntityId(out var entityId); // вернет true и заполнит entityId из EntityId, если он заполнен, иначе вернет false и в entityId будет пустой гуид

ПолеСсылки.TryGetDataTypeId(out var dataTypeId); // вернет true и заполнит dataTypeId из DataTypeId, если он заполнен, иначе вернет false и в dataTypeId будет пустой гуид

Metadata.DataTypes GetDataType(); //возвращает тип данных ссылки. Если тип не пределено, то вернет Empty

Также можно обращаться к полям напрямую:

bool hasEntityId = ПолеСсылки.EntityId.HasValue; // вернет true если заполнено
Guid entityId = ПолеСсылки.EntityId.Value // вернет значение или исключение, если значение не заполнено

Еще про работу с Nullable: https://docs.microsoft.com/ru-ru/dotnet/csharp/language-reference/builtin-types/nullable-value-types.

Другие функции

Свойства

  • CurrentProcessId.

  • LastException.

Проверки:

bool ok = IsNullOrDefault(object value)

Метаданные

Для работы с метаданными доступны следующие перечисления:

Тип метаданных

namespace

enum name

Методы поиска

Дополнительные методы

Тип данных

Metadata

DataTypes

MetadataInfo.SearchDataType

LinkType CreateLink(Guid entityId)

Динамический тип данных

Metadata

Dynamics

MetadataInfo.SearchDynamic

_

Перечисление

Metadata

Enums

MetadataInfo.SearchEnum

_

Метаданные систем

Metadata

SM

MetadataInfo.SearchSM

_

Алгоритм/Бизнес процесс

Metadata

Functions

MetadataInfo.SearchFunction

_

Система

Metadata

Systems

MetadataInfo.SearchSystem

SystemInfo GetSystemInfo()

Роли

Metadata

Roles

MetadataInfo.SearchRole

CredentialRole GetRoleInfo()

Обработчики

Metadata

Handlers

_

HandlerInfo GetHandlerInfo()

Методы поиска возвращают соответствующее значение перечисления. Если не найдено, то возвращается значение Empty. Поиск возможен по имени или Id объекта:

Metadata.* MetadataInfo.Search*(string name, bool caseInsensitive = false)
Metadata.* MetadataInfo.Search*(Guid id)

Для всех значений перечислений доступны методы:

  • Guid GetId() - возвращает внутренний идентификатор объекта

  • string GetName() - возвращает имя объекта

Генерируемые перечисления

Тип метаданных: Тип данных Перечисление: Metadata.DataTypes Методы расширения для перечисления:

  • Guid GetId() – возвращает идентификатор типа

  • string GetName() – возвращает название перечисления в виде строки

  • LinkType CreateLink() - создает ссылку этого типа данных

  • LinkType CreateLink(Guid entityId) - создает ссылку этого типа данных с идентификатором entityId

Тип метаданных: Классификаторы Перечисление: Metadata.Classifiers Методы расширения для перечисления:

Guid GetId() – возвращает идентификатор классификатора
string GetName() – возвращает название перечисления в виде строки

Тип метаданных: Перечисления Перечисление: Metadata.Enums Методы расширения для перечисления:

Guid GetId() – возвращает идентификатор перечисления
string GetName() – возвращает название перечисления в виде строки

Тип метаданных: Функции Перечисление: Metadata.Functions Методы расширения для перечисления:

Guid GetId() – возвращает идентификатор функции
string GetName() – возвращает название перечисления в виде строки

Тип метаданных: Обработчики Перечисление: Metadata.Handlers Методы расширения для перечисления:

Guid GetId() – возвращает идентификатор обработчика
string GetName() – возвращает название перечисления в виде строки
HandlerInfo GetHandlerInfo() – возвращает класс с описанием обработчика
public class HandlerInfo
{
Guid Id //идентификатор обработчика
Name //имя
string Description //описание
ConnectorType ConnectorType //тип коннектора
PropertiesCollection Parameters // коллекция с параметрами обработчика
bool WaitResponse //ожидает ли ответа
bool WaitArray //принимает массив или один элемент
Metadata.DataTypes WaitDataType //какой тип данных принимает (опционально)
Metadata.SM WaitSystemDataType //какой тип метаданных принимает (опционально)
}
public enum ConnectorType
{
        None, _1C, File, Database, Custom, Web, WebSimple
}

Тип метаданных: Роли Перечисление: Metadata.Roles Методы расширения для перечисления:

Guid GetId() – возвращает идентификатор роли
string GetName() – возвращает название перечисления в виде строки
CredentialRole GetRoleInfo() – возвращает объект роли.

Тип метаданных: Системные типы (метаданные) Перечисление: Metadata.SM Методы расширения для перечисления:

Guid GetId() – возвращает идентификатор системного типа
string GetName() – возвращает название перечисления в виде строки

Тип метаданных: Системы Перечисление: Metadata.Systems Методы расширения для перечисления:

Guid GetId() – возвращает идентификатор системного типа
string GetName() – возвращает название перечисления в виде строки
SystemInfo GetSystemInfo() – возвращает объект с информацией о системе
Metadata.Systems GetSystemByGuid() – возвращает систему по идентификатору
class SystemInfo
{
bool IsActive; //включена
string[] Servers; //список серверов системы
ConnectorType ConnectorType; //тип коннектора
}

Прочие методы

DataTypesExtensions.DataTypes ById(Guid id) – возвращает значение перечисления типов данных по идентификатору
DataTypesExtensions.Classifiers ById(Guid id) – возвращает значение перечисления классификаторов по идентификатору
EnumsExtensions.Enums ById(Guid id) – возвращает значение перечисления по идентификатору
FunctionsExtensions.Functions ById(Guid id) – возвращает значение перечисления функций по идентификатору
HandlersExtensions.Handlers ById(Guid id) – возвращает значение перечисления обработчиков по идентификатору
RolesExtensions.Roles ById(Guid id) – возвращает значение перечисления ролей по идентификатору
SMExtensions.SM ById(Guid id) – возвращает значение перечисления системных типов по идентификатору
SystemsExtensions.Systems ById(Guid id) – возвращает значение перечисления систем по идентификатору

Запуск вложенных БП/Алгоритмов из кода

Запуск вложенных Бизнес процессов и Алгоритмов:

var BP1 = new Вызываемый(); //создание экземпляра BP1 бизнес-процесса, где Вызываемый - имя БП

//Установка параметров BP1
BP1.строка = "Здравствуй"; // где "строка" - строчная переменная бизнес-процесса Вызываемый
BP1.Сложное.число = 1; // где "Сложное" - переменная пользовательского типа или сложная переменная бизнес-процесса Вызываемый, а "Сложное.число" - числовое поле этой переменной

//Запуск сформированного BP1 на заданных параметрах
Executor.Start(BP1); // без ожидания завершения
Executor.Execute(BP1); // с ожиданием завершения

Внимание

Запуск Бизнес процесса методом Executor.Start или Executor.Execute поддерживается только из шага Алгоритм. При вызове из других шагов выполнение методов не производится.

Массивы

Функции доступные для массивов:

  • AddElement(): добавление значения по умолчанию в массив.

    Пример использования: mas.AddElement()

  • CreateElement(): создает, но не добавляет значение по умолчанию для массива.

    Пример использования: mas.CreateElement()

Работа с банком

  • Методы получения данных (Get/Exists/Query) доступны из трансформаторов, определения функций, алгоритмов и шагов Алгоритм.

  • Методы изменения данных (Write/Delete) доступны только из алгоритмов и шагов Алгоритм.

Методы, принимающие Message, ожидают в теле сообщения json с нужными объектами, а в DataType - идентификатор целевого типа.

Примечание

Оператор UNION ALL в запросах к Банку данных не поддерживается.

Запись в банк

bool Write<T>(T entity, bool waitResponse = true) where T : IDataType;
bool Write<T>(T entity, out Guid entityId, bool waitResponse = true) where T : IDataType;

bool Write<T>(OwnList<T> entities, bool waitResponse = true) where T : IDataType;
bool Write<T>(OwnList<T> entities, out OwnList<Guid> entitiesIds, bool waitResponse = true) where T : IDataType;

bool Write(Message msg, bool waitResponse = false);
bool Write(Message msg, out Guid id, bool waitResponse = false);
bool Write(Message msg, out List<Guid> ids, bool waitResponse = false);

bool Write(OwnList<BaseClass> entitiesBase, bool waitResponse = true);
bool Write(OwnList<BaseClass> entitiesBase, out OwnList<Guid> entitiesIds, bool waitResponse = true);

bool Write(BaseClass entity, bool waitResponse = true);
bool Write(BaseClass entity, out Guid entityId, bool waitResponse = true);

Методы удаления

bool Delete(IDataType entity, bool waitResponse = true);

bool Delete<T>(Guid EntityId, bool waitResponse = true) where T : IDataType;

bool Delete(Guid EntityId, Guid typeId, bool waitResponse = true);
bool Delete(Guid EntityId, Metadata.DataTypes dataType, bool waitResponse = true);

bool Delete<T>(OwnList<T> entities, bool waitResponse = true) where T : IDataType;

bool Delete(LinkType link, bool waitResponse = true);
bool Delete(OwnList<LinkType> entities, bool waitResponse = true);

bool Delete(Message msg, bool waitResponse = true);

bool Delete<T>(T entity, bool waitResponse = true) where T : IDataType;
bool Delete<T>(OwnList<Guid> entitiesIds, bool waitResponse = true) where T : IDataType;

bool Delete(OwnList<Guid> entitiesIds, Guid typeId, bool waitResponse = true);
bool Delete(OwnList<Guid> entitiesIds, Metadata.DataTypes dataType, bool waitResponse =true);

bool Delete(BaseClass entity, bool waitResponse = true);
bool Delete(OwnList<BaseClass> entities, bool waitResponse = true);

Поиск данных

void Query(string query, Message message);
void QuerySimple(string query, Message message);
void QueryObject(string query, Message message);

void Query(string query, PropertiesCollection parameters, Message message);
void QuerySimple(string query, PropertiesCollection parameters, Message message);
void QueryObject(string query, PropertiesCollection parameters, Message message);

void Query<T>(string query, IList<T> resultList);
void QuerySimple<T>(string query, IList<T> resultList); OwnList<T> QuerySimple<T>(string query);
void QueryObject<T>(string query, IList<T> resultList); OwnList<T> QueryObject<T>(string query);

void Query<T>(string query, PropertiesCollection parameters, IList<T> resultList);
void QuerySimple<T>(string query, PropertiesCollection parameters, IList<T> resultList);
void QueryObject<T>(string query, PropertiesCollection parameters, IList<T> resultList);

Получение данных

T Get<T>(Guid entityId, Guid type = default) where T : new();
T Get<T>(LinkType type) where T : new();
OwnList<T> Get<T>(OwnList<Guid> entityIds);
OwnList<T> Get<T>(OwnList<LinkType> entityIds);

bool TryGet<T>(Guid entityId, out T val);
bool TryGet<T>(LinkType link, out T val);
bool TryGet<T>(OwnList<Guid> entityIds, out OwnList<T> val);

//В NotExists возвращается список неудач, возвращает true, если получен хотя бы один объект

bool TryGet<T>(OwnList<Guid> entityIds, out OwnList<T> val, out OwnList<Guid> notExists);
bool TryGet<T>(OwnList<LinkType> links, out OwnList<T> val);
bool TryGet<T>(OwnList<LinkType> links, out OwnList<T> val, out OwnList<LinkType> notExists);
bool TryGet<T>(OwnList<LinkType> links, out OwnList<T> val, out OwnList<Guid> notExists);

Проверка существования записей

//Методы для проверки на существование объектов, не существующие возвращаются в NotExists
//Для OwnList возвращает true, если найден хотя бы один объект и all==false. Возвращает true, если найдены все объекты и all==true.
bool Exists<T>(Guid entityId);
bool Exists(Guid entityId, Guid dataTypeId);
bool Exists(Guid entityId, Metadata.DataTypes dataType);
bool Exists(LinkType link);
bool Exists(OwnList<Guid> entityIds, out OwnList<Guid> notExists, Guid dataTypeId, bool all =
false);
bool Exists(OwnList<Guid> entityIds, out OwnList<Guid> notExists, Metadata.DataTypes
dataType, bool all = false);
bool Exists<T>(OwnList<Guid> entityIds, out OwnList<Guid> notExists, bool all = false);
bool Exists(OwnList<BaseClass> entities, out OwnList<LinkType> notExists, bool all = false);
bool Exists(OwnList<BaseClass> entities, out OwnList<BaseClass> notExists, bool all = false);
bool Exists(OwnList<IDataType> entities, out OwnList<LinkType> notExists, bool all = false);
bool Exists(IDataType entity);
bool Exists(Message entity);
bool Exists(BaseClass entity);
bool Exists(OwnList<IDataType> entities, out OwnList<IDataType> notExists, bool all = false);
bool Exists(OwnList<LinkType> links, out OwnList<LinkType> notExists, bool all = false);
bool Exists<T>(OwnList<LinkType> links, out OwnList<LinkType> notExists, bool all = false);

Credential (управление пользователями)

Подробное описание базового сервиса управления пользователями находится в соответствующем разделе.

Для работы с метаданными Роли используется перечисление Metadata.Roles. Рекомендуется для работы с ролями использовать именно перечисление. Назначение прав и управление учетными записями описаны в разделах Пользователи и Учетные данные систем.

Структура типа CredentialUser

public Guid EntityId { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public string Comment { get; set; }
public string Email { get; set; }
public bool IsEnabled { get; set; } = true;
public Guid FolderId { get; set; }

Структура типа CredentialFolder

public Guid EntityId { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public string Comment { get; set; }
public Guid ParentId { get; set; }

Структура типа CredentialRole

public Guid EntityId { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public string Comment { get; set; }
bool IsBusinessRole { get; set; }
OwnList<CredentialRole> Roles { get; set; } = new OwnList<CredentialRole>();

Методы для работы с пользователями/ролями/папками вызываются через объект Credential.

Пользователи

//Методы для работы с текущим пользователем
        bool IsAuthorized() //возвращает true, если в сообщении процесса был заполнен UserId
        CredentialUser GetCurrentUser() //возвращает текущего пользователя
        OwnList<Metadata.Roles> GetCurrentRoles(bool hierarchy = true) //возвращает роли текущего пользователя
        OwnList<Metadata.Roles> GetCurrentUserContainsRoles(bool hierarchy = true) //возвращает роли текущего пользователя, включая вложенные роли в бизнес-роли
        bool CurrentUserHasRole(Metadata.Roles role, bool hierarchy= true) //проверяет, установлена ли роль текущему пользователю
        bool CurrentUserHasContainsRole(Metadata.Roles role, bool hierarchy= true) //проверяет, установлена ли роль текущему пользователю, включая вложенные роли в бизнес-роли

//Чтение пользователей
        OwnList<CredentialUser> GetUsers(bool enabledOnly = true);

        CredentialUser GetUserById(Guid userId);
        CredentialUser TryGetUserById(Guid userId);

        CredentialUser GetUserByName(string name);
        CredentialUser TryGetUserByName(string name);

        CredentialUser GetUserByEmail(string email);
        CredentialUser TryGetUserByEmail(string email);

        bool UserExists(Guid userId);
        bool UserExists(string userName);
//Изменение пользователей
void AddUser(CredentialUser user);

void UpdateUser(CredentialUser user);

void DeleteUser(Guid userId);
void DeleteUser(string name);
void DeleteUser(CredentialUser user);

void DisableUser(Guid userId);
void DisableUser(CredentialUser user);
void DisableUser(string name);

void EnableUser(Guid userId);
void EnableUser(CredentialUser user);
void EnableUser(string name);

void SetPassword(Guid userId, string password);
void SetPassword(CredentialUser user, string password);
void SetPassword(string name, string password);

Группы пользователей

//Чтение групп
        OwnList<CredentialFolder> GetFolders();

        CredentialFolder GetFolderById(Guid folderId);
        CredentialFolder TryGetFolderById(Guid folderId);

        CredentialFolder GetFolderByName(string folderName, Guid? parentId = null, Guid? folderId= null);
        CredentialFolder TryGetFolderByName(string folderName, Guid? parentId = null, Guid?folderId = null);

        bool FolderExists(Guid folderId);
        bool FolderExists(string folderName);

//Изменение групп
        void AddFolder(CredentialFolder folder);

        void UpdateFolder(CredentialFolder folder);

        void DeleteFolder(Guid folderId);

        void DeleteFolder(CredentialFolder folder);

Иерархия пользователей и групп

//Получить группу
        CredentialFolder GetFolder(CredentialUser user);
        CredentialFolder GetFolder(CredentialFolder user);
        CredentialFolder GetFolderByUserId(Guid userId);

//Изменить группу
        void ChangeFolder(CredentialFolder folder, CredentialFolder parent);
        void ChangeFolder(CredentialUser user, CredentialFolder folder);

Роли

//Чтение ролей

        OwnList<CredentialRole> GetRoles();

        CredentialRole GetRoleById(Guid roleId);
        CredentialRole GetRoleByName(string roleName);

        bool RoleExists(Guid roleId);
        bool RoleExists(string roleName);

Роли пользователей и групп

//Чтение
        OwnList<Metadata.Roles> GetUserRoles(CredentialUser user, bool hierarchy = true);
        OwnList<Metadata.Roles> GetUserContainsRoles(CredentialUser user, bool hierarchy = true);

        bool UserHasRole(CredentialUser user, Metadata.Roles role, bool hierarchy= true);
        bool UserHasRole(CredentialUser user, Guid roleId, bool hierarchy= true);
        bool UserHasContainsRole(CredentialUser user, Metadata.Roles role, bool hierarchy = true);
        bool UserHasContainsRole(CredentialUser user, Guid roleId, bool hierarchy = true);

        OwnList<Metadata.Roles> GetFolderRoles(CredentialFolder folder, bool hierarchy = true);
        OwnList<Metadata.Roles> GetFolderContainsRoles(CredentialFolder folder, bool hierarchy =true);

        bool FolderHasRole(CredentialFolder folder, Metadata.Roles role, bool hierarchy= true);
        bool FolderHasRole(CredentialFolder folder, Metadata.Roles role, bool hierarchy= true);
        bool FolderHasRole(CredentialFolder folder, Guid roleId, bool hierarchy = true);
        bool FolderHasContainsRole(CredentialFolder folder, Metadata.Roles role, bool hierarchy=true);
        bool FolderHasContainsRole(CredentialFolder folder, Metadata.Roles role, bool hierarchy=true);
        bool FolderHasContainsRole(CredentialFolder folder, Guid roleId, bool hierarchy = true);

//Изменение
        void AddUserRole(CredentialUser user, Metadata.Roles role);
        void AddUserRole(Guid userId, Guid roleId);
        void AddUserRole(CredentialUser user, CredentialRole role);
        void AddUserRole(CredentialUser user, Guid roleId);

        void DeleteUserRole(CredentialUser user, Metadata.Roles role);
        void DeleteUserRole(Guid userId, Guid roleId);
        void DeleteUserRole(CredentialUser user, CredentialRole role);
        void DeleteUserRole(CredentialUser user, Guid roleId);

        void AddFolderRole(CredentialFolder folder, Metadata.Roles role);
        void AddFolderRole(CredentialFolder folder, Guid role);

        void DeleteFolderRole(CredentialFolder folder, Metadata.Roles role);
        void DeleteFolderRole(CredentialFolder folder, Guid role);

Дополнительные открытые и секретные свойства пользователей

//Чтение
PropertiesCollection GetAdditionalProperties(CredentialUser user);
T GetAdditionalProperty<T>(CredentialUser user, string propertyName);
PropertiesCollection GetSecretProperties(CredentialUser user);
T GetSecretProperty<T>(CredentialUser user, string propertyName);

bool AdditionalPropertyExists(string propertyName);
bool SecretPropertyExists(string propertyName);

//Изменени
void SetAdditionalProperties(CredentialUser user, PropertiesCollection collection);
void SetAdditionalProperty<T>(CredentialUser user, string propertyName, T value);

void SetSecretProperties(CredentialUser user, PropertiesCollection collection);
void SetSecretProperty<T>(CredentialUser user, string propertyName, T value);

Значения параметров

Параметр hierarchy позволяет учитывать роли, установленные для родительских элементов.

Примеры использования методов Credential в шаге Алгоритм бизнес процесса

Для использования примеров создать Бизнес-процесс с шагом Алгоритм и выполнять его, например, через триггер.

Добавление пользователя

Код в алгоритме:

CredentialUser User1 = new CredentialUser();
User1.EntityId = Guid.NewGuid();
User1.Name = "Vasya3";
User1.Description = "Vasya Pupkin";
User1.Comment = "123";
User1.Email = "name1@gmail.com";
User1.IsEnabled = true;
Credential.AddUser(User1);

Обновление пользователя

Код в алгоритме:

CredentialUser User1 = Credential.GetUserByName("Vasya3");
User1.Name = "Vova";
User1.Description = "Vova Ivanov";
User1.Comment = "321";
User1.Email = "name1@gmail.com";
User1.IsEnabled = true;
Credential.UpdateUser(User1);

Установка пароля

Код в алгоритме:

Credential.SetPassword(Guid.Parse("9739520D-D795-4893-BA5E-EE937BD83611"), "Pwd");

Отключение / Включение пользователя

Код в алгоритме:

Credential.DisableUser(Guid.Parse("9739520D-D795-4893-BA5E-EE937BD83611"));

Или

Credential.EnableUser(Guid.Parse("9739520D-D795-4893-BA5E-EE937BD83611"));

Добавление значения дополнительного свойства

Код в алгоритме для добавления значения дополнительного свойства:

CredentialUser user1 = Credential.GetUserByName("Vasya3");
Credential.SetAdditionalProperty(user1, "Религия", "джедай");

Или использовать

CredentialUser user1 = Credential.GetUserByName("Vasya3");
PropertiesCollection addcollection = Credential.GetAdditionalProperties(user1);
addcollection.AddValue( "Религия", "джедай");
Credential.SetAdditionalProperties(user1, addcollection);

Добавление значения секретного свойства

Код в алгоритме для добавления значения секретного свойства:

CredentialUser user1 = Credential.GetUserByName("Vasya3");
Credential.SetSecretProperty(user1, "Зарплата", "123123");

Или используйте следующий код:

CredentialUser user1 = Credential.GetUserByName("Vasya3");
PropertiesCollection secretcollection = Credential.GetSecretProperties(user1);
secretcollection.AddValue("Зарплата", "123123");
Credential.SetSecretProperties(user1, secretcollection);

Удаление пользователя

Код в алгоритме:

Credential.DeleteUser(Guid.Parse("577297B5-C5E5-439A-B966-251F9D4811FC"));

Добавление папки в таблицу dbo.folders

Код в алгоритме:

CredentialFolder fold1 = new CredentialFolder();
fold1.EntityId = Guid.NewGuid();
fold1.Name = "FolderVasya6";
fold1.Description = "Folder6";
fold1.Comment = "1236";
Credential.AddFolder(fold1);

Добавление пользователя в таблицу dbo.folders

Код в алгоритме:

CredentialUser User1 = new CredentialUser();
User1.EntityId = Guid.NewGuid();
User1.Name = "Vasya3";
User1.Description = "Vasya Pupkin";
User1.Comment = "123";
User1.Email = "name1@gmail.com";
User1.IsEnabled = true;
Credential.AddUser(User1);

Обновление папки

Код в алгоритме:

var propId1 = Guid.Parse("CB7EB008-8DC3-4C5A-8A11-6163D72D2EE0");
CredentialFolder fold1 = Credential.GetFolderById(propId1);
fold1.Name = "FolderVasya_up";
fold1.Description = "Folder_update";
fold1.Comment = "123_update";
Credential.UpdateFolder(fold1);

Изменение папки у пользователя

Код в алгоритме:

CredentialUser user1 = Credential.GetUserByName("Vasya3");
Logger.Info($"begin TEST777_DT251_aaa");
CredentialFolder fold1 = Credential.GetFolderById(Guid.Parse("E55F1242-B391-4A80-BC72-93BC107342B2"));
Logger.Info($"begin TEST777_DT251_bbb");
Credential.ChangeFolder(user1, fold1);

Удаление папки

Код в алгоритме:

CredentialFolder fold1 = Credential.GetFolderById(Guid.Parse("E4D9CB4C-3F26-4FF4-B7A9-F6A7EF3AAD4D"));
Credential.DeleteFolder(fold1);

Получение ролей пользователя

Код в алгоритме:

CredentialUser user1 = Credential.GetUserByName("ИмяПользователя");
OwnList<Metadata.Roles> roles = Credential.GetUserRoles(user1, true);
Logger.Info($"Пользователь: {user1}");
foreach(Metadata.Roles role in roles)
{
        Logger.Info($"Роли GetUserRoles true: {role}");
}
OwnList<Metadata.Roles> roles1 = Credential.GetUserRoles(user1, false);
Logger.Info($"Пользователь: {user1}");
foreach(Metadata.Roles role in roles1)
{
        Logger.Info($"Роли GetUserRoles false: {role}");
}
OwnList<Metadata.Roles> roles2 = Credential.GetUserContainsRoles(user1, true);
Logger.Info($"Пользователь: {user1}");
foreach(Metadata.Roles role in roles2)
{
        Logger.Info($"Роли GetUserContainsRoles true: {role}");
}
OwnList<Metadata.Roles> roles3 = Credential.GetUserContainsRoles(user1, false);
Logger.Info($"Пользователь: {user1}");
foreach(Metadata.Roles role in roles3)
{
        Logger.Info($"Роли GetUserContainsRoles false: {role}");
}

Роли Credential в управлении пользователями

Добавление роли в ЦУ и в Credential

Создайте роль в ЦН.

Получить роли можно в Swagger по запросу:

GET /api/metadata/roles - Получить роли

Код в алгоритме:

Credential.AddUserRole(Guid.Parse("85FC1A65-B0D8-4F5E-994E-8C5BEA6C6A61"),
Guid.Parse("385ff9bd-6006-45be-913b-c97fdba002e9"));

Где первый Guid - пользователя, второй Guid - роли.

Добавление роли в папку Credential

Код в алгоритме:

CredentialFolder fold = Credential.TryGetFolderByName("FolderVasya");
Credential.AddFolderRole(fold, Guid.Parse("88d1af76-e997-4ef2-9ade-dd4efe20af07"));

Где FolderVasya - имя созданной ранее папки, Guid - роли.

Удаление роли Credential

Код в алгоритме:

Credential.DeleteUserRole(Guid.Parse("85FC1A65-B0D8-4F5E-994E-8C5BEA6C6A61"),
Guid.Parse("385ff9bd-6006-45be-913b-c97fdba002e9"));

Где первый Guid - пользователя, второй Guid - роли.

Удаление роли из ЦУ

Для удаления выберите роль в списке рабочей области и нажмите на кнопку со значком Удалить.

При удалении роли из ЦУ удалятся записи в таблице role_users и role_folders.

Учетные данные Credential

В данном разделе представлены методы, используемые для работы с учетными данными.

Добавление внешнего пользователя Credential

  1. Откройте Swagger сервера и найдите следующий метод:

POST/api/credential/externalUsers/users - Добавить пользователя

  1. Заполните все необходимые данные, например:

    {
            "name": "user01",
            "login": "user01",
            "description": "user01test",
            "comment": "comment111",
            "systemId": "0abb2f56-30bf-4b4b-8049-2e8ae592892f",
            "internalUserId": "90AD1E95-BA6F-4AE0-8E1B-1CF2D74FAAA4"
    }
    

Где

  • entityId: идентификатор внешнего пользователя (в примере пустой, чтобы сгенерировался автоматически).

  • name: имя внешнего пользователя.

  • login: логин, если для авторизации во внешней системе нужно написать, например, домен перед именем, тогда в этом поле будет реальная строка для ввода логина юзера при авторизации.

  • description: описание внешнего пользователя.

  • comment: комментарий.

  • systemId: идентификатор системы или сервиса, который использует эту учетную запись.

  • internalUserId: идентификатор пользователя Credential.

Установка пароля внешнему пользователю Credential

Открытый ключ действителен в течение 1 минуты. По истечении времени необходимо запросить снова открытый ключ.

  1. Выполнить метод, указав идентификатор внешнего пользователя:

Get/api/credential/externalUsers/publicKey - Получить ключ для шифрования пароля Скопировать полученный ключ.

  1. Выполнить метод, указав пароль и скопированный ключ:

Get/api/credential/externalUsers/users/test-encrypt - Тестовый метод шифрования данных

  1. Выполнить метод, указав идентификатор внешнего пользователя и зашифрованный пароль:

Get/api/credential/externalUsers/password - Установить пароль

Получить внешнего пользователя по имени

В Swagger сервера найти следующий метод:

GET/api/credential/externalUsers/users - Получить внешних пользователей по имени.

Удалить внешнего пользователя Credential

В Swagger сервера найти следующий метод:

DELETE api/credential/externalUsers/users/{id} - Удалить внешнего пользователя.

Транспортные функции

В алгоритмах и процессах для регистрации и отправки сообщений доступен фасад Transport.

Отправка сообщения получателям:

void SendMessage(Message message, OwnList<Guid> receivers, Guid? handlerId = null);
void SendMessage(string message, OwnList<Guid> receivers, Guid? handlerId = null);
void SendMessage(BaseClass message, OwnList<Guid> receivers, Guid? handlerId = null);
void SendMessage(byte[] message, OwnList<Guid> receivers, Guid? handlerId = null);

void SendMessage(Message message, Guid receiver, Guid? handlerId = null);
void SendMessage(string message, Guid receiver, Guid? handlerId = null);
void SendMessage(BaseClass message, Guid receiver, Guid? handlerId = null);
void SendMessage(byte[] message, Guid receiver, Guid? handlerId = null);

void SendMessage(Message message, string searchPattern, Guid? handlerId = null);
void SendMessage(BaseClass message, string searchPattern, Guid? handlerId = null);
void SendMessage(string message, string searchPattern, Guid? handlerId = null);
void SendMessage(byte[] message, string searchPattern, Guid? handlerId = null);

void SendMessage(Message message, Metadata.Systems system, Metadata.Handlers? handler = null);
void SendMessage(Message message, OwnList<Metadata.Systems> systems, Metadata.Handlers? handler = null);
void SendMessage(string message, Metadata.Systems system, Metadata.Handlers? handler = null);
void SendMessage(string message, OwnList<Metadata.Systems> systems, Metadata.Handlers? handler = null);
void SendMessage(byte[] message, Metadata.Systems system, Metadata.Handlers? handler = null);
void SendMessage(byte[] message, OwnList<Metadata.Systems> systems, Metadata.Handlers? handler = null);
void SendMessage(BaseClass message, Metadata.Systems system, Metadata.Handlers? handler = null);
void SendMessage(BaseClass message, OwnList<Metadata.Systems> systems, Metadata.Handlers? handler = null);

Отправка ответного сообщения источнику:

SendResponseMessage(Message message);
SendResponseMessage(string message);
SendResponseMessage(BaseClass message);
SendResponseMessage(byte[] message);
SendResponseMessage(Message message, Message request);
SendResponseMessage(string message, Message request);
SendResponseMessage(BaseClass message, Message request);
SendResponseMessage(byte[] message, Message request);

Регистрация нового сообщения для обработки - регистрирует сообщение для обработки на сервере, сообщение попадает в определятор:

RegisterMessage(Message message);
RegisterMessage(BaseClass message);
RegisterMessage(string message);
RegisterMessage(byte[] message);

Типы данных

Тип DateTime

Работа с датами выполняется с учетом Kind. Для сравнения дат рекомендуется также учитывать Kind и использовать методы сравнения https://docs.microsoft.com/ru-ru/dotnet/api/system.datetime.compare?view=net-5.0.

Поддерживаются следующие форматы представления даты и времени:

  • ISO 8601: международный стандарт представления даты и времени.

    2024-03-15T13:45:30Z
    2024-03-15T13:45:30+03:00
    2024-03-15
    
  • .NET JSON Date (Microsoft формат): формат, используемый в .NET при сериализации даты в JSON. Представляет количество миллисекунд, прошедших с 01.01.1970 (Unix Epoch), с указанием смещения часового пояса.

    /Date(1710500730000)/
    /Date(1710500730000+0300)/
    
  • RFC1123: текстовый формат даты и времени, используемый, например, в HTTP-заголовках.

    Fri, 15 Mar 2024 13:45:30 GMT
    Mon, 01 Jan 2024 00:00:00 GMT
    

Тип DataType

Типы данных, созданные в меню Типы данных, представляют собой класс DataType. Все объекты DataType, а также сложные переменные унаследованы от класса BaseClass.

В классе DataType добавлены одноименные свойства в соответствии с полями типа данных для программной работы с полями типа.

В DataType реализованы следующие методы для программной работы:

  • Получение строкового значения поля по имени поля:

    string GetFieldStrValue(string fieldName)
    

    Например:

    string inn = контрагент.GetFieldStrValue("ИНН")
    
  • Проверка наличия в типе данных поля по имени:

    bool HasField(string fieldName);
    

Категории и атрибуты

В DataType для каждой прикрепленной к типу категории будет создано одноименное свойство. В прикрепленной категории доступна работа с атрибутами типа данных, относящимся к категории.

Например, значение атрибута Диаметр с настроенной категорией Классификатор ТМЦ и прикрепленного к номенклатуре будет доступно следующим образом:

Номенклатура.КлассификаторТМЦ.Атрибуты.Диаметр

Для работы с атрибутами реализованы следующие методы:

  • Установка значения атрибута SetAttrValue:

    bool КлассификаторТМЦ.Атрибуты.SetAttrValue(КлассификаторТМЦ_Атрибут.ГОСТ, string val)
    bool КлассификаторТМЦ.Атрибуты.SetAttrValue(КлассификаторТМЦ_Атрибут.Диаметр, int val)
    

Контейнер BaseClass

Все объекты DataType, SystemDataType, а также сложные переменные унаследованы от класса BaseClass.

Доступные методы и свойства:

bool IsDefault() //Возвращает true, если все поля объекта заполнены значениями по умолчанию
Metadata.DataTypes GetDataType() //значение перечисления Types.DataTypes, соответствующее типу текущего объекта

Ссылка LinkType

Объект LinkType описывает ссылку на объект. Содержит 2 поля:

  • Guid EntityId

  • Guid DataTypeId

Создать ссылку можно с помощью метода CreateLink из Metadata.DataType:

LinkType Metadata.DataTypes.MyType.CreateLink();
LinkType Metadata.DataTypes.MyType.CreateLink(Guid entityId);

Поддерживает неявное преобразование в тип Guid, т.е. можно написать так:

LinkType lt = new LinkType();
Guid dd = lt; // будет установлено значение поля EntityId

Интерфейсы

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

Доступны встроенные механизмы для работы с интерфейсами:

тип1.CopyTo((IМойИнтерфейс)тип2); //в тип2 копируются поля интерфейса IМойИнтерфейс из тип1

Системные поля

Если у типа данных проставлен признак Объект банка данных, то при сохранении такого типа система создает таблицу указанной пользователем структуры и класс DataInfo c сервисными полями:

  • DateTime created NOT NULL;

  • DateTime updated NOT NULL;

  • guid version NOT NULL.

Данные поля не отображаются в центре настройки.

../_images/image19.png

Заполнение сервисных полей:

  1. DateTime created Заполняется текущей датой сервера на момент записи для запроса insert, например, при выполнении шага Запись. Формат даты в UTC.

  2. DateTime updated Заполняется текущей датой сервера на момент записи для запроса insert или update.

При обновлении данных у типа система заменила дату обновления:

  1. guid version - заполняется из принятого сообщения в банк.

Получить значения системных полей можно при использовании шагов:

Пример получения значений системных полей:

синтаксис <ТипДанных>.<НазваниеСистемногоПоля>=“<дата>“

Шаг Поиск: в строке поиска написать Животные.Created :“2022-05-2406:22:23.1600000“. При выполнении шага Поиск система вернет ответ следующей структуры:

../_images/image22.png
../_images/image23.png

Утилиты

Утилиты по трансформации тела сообщения UserModuleUtils

Класс UserModuleUtils содержит публичные свойства для работы с телом сообщения, копированием, заменой, установкой свойств тела сообщения, если тело представлено в формате Json или XML, а также трансформацией формата Json в XML и XML в Json.

Все функции вызываются из статичного класса UserModuleUtils. Статичный класс UserModuleUtils доступен только из программных модулей (вызов напрямую из трансформаций запрещен).

Функции копирования

/// <summary>
/// Копирование параметров тела сообщения
/// </summary>
/// <param name="message">Сообщение</param>
/// <param name="copyProps">Параметры для копирования</param>
/// <param name="appendIfNotExists">Признак - добавлять параметр если не существует</param>
/// <returns><c>true</c> операция завершена успешно, <c>false</c> иначе</returns>
bool CopyTo(Message message, OwnDictionary<string, string> copyProps, bool appendIfNotExists = true)
/// <summary>
/// Копирование параметров тела сообщения
/// </summary>
/// <param name="message">Сообщение</param>
/// <param name="copyProps">Параметры для копирования</param>
/// <param name="appendIfNotExists">Признак - добавлять параметр если не существует</param>
/// <returns><c>true</c> операция завершена успешно, <c>false</c> иначе</returns>
bool CopyTo(Message message, OwnDictionary<string, OwnList<string>> copyProps, bool appendIfNotExists = true)
/// <summary>
/// Копирование параметров тела сообщения
/// </summary>
/// <param name="message">Сообщение</param>
/// <param name="xpathFrom">Путь к свойству источнику</param>
/// <param name="xpathTo">Путь к свойству назначения</param>
/// <param name="appendIfNotExists">Признак - добавлять параметр если не существует</param>
/// <returns><c>true</c> операция завершена успешно, <c>false</c> иначе</returns>
bool CopyTo(Message message, string xpathFrom, string xpathTo, bool appendIfNotExists = true)
/// <summary>
/// Копирование параметров тела для строки
/// </summary>
/// <param name="data">Строка содержащая JSON или XML</param>
/// <param name="dataType">Тип данных в строке</param>
/// <param name="copyProps">Параметры для копирования</param>
/// <param name="dataResult">Переменная для результата копирования</param>
/// <param name="appendIfNotExists">Признак - добавлять параметр если не существует</param>
/// <returns><c>true</c> операция завершена успешно, <c>false</c> иначе</returns>
bool CopyTo(string data, MessageBodyType dataType, OwnDictionary<string, OwnList<string>> copyProps, out string dataResult, bool appendIfNotExists = true)
/// <summary>
/// Копирование параметров тела для массива байт
/// </summary>
/// <param name="data">Строка содержащая JSON или XML в виде массива байт</param>
/// <param name="dataType">Тип данных в строке</param>
/// <param name="copyProps">Параметры для копирования</param>
/// <param name="dataResult">Переменная для результата копирования</param>
/// <param name="appendIfNotExists">Признак - добавлять параметр если не существует</param>
/// <returns>Результат копирования в строке</returns>
bool CopyTo(byte[] data, MessageBodyType dataType, OwnDictionary<string, OwnList<string>> copyProps, out byte[] dataResult, bool appendIfNotExists = true)

Функции установки значения

<code csharp>
/// <summary>
/// Установка параметров по указанному xpath
/// </summary>
/// <param name="message">сообщение</param>
/// <param name="copyProps">Параметры для копирования</param>
/// <param name="appendIfNotExists">Признак - добавлять параметр если не существует</param>
/// <returns><c>true</c> операция завершена успешно, <c>false</c> иначе</returns>
bool SetValue(Message message, OwnDictionary<string, object> copyProps, bool appendIfNotExists = true)
/// <summary>
/// Установка параметра по указанному xpath
/// </summary>
/// <param name="message">Сообщение</param>
/// <param name="xpathTo">Путь к свойству</param>
/// <param name="value">Значение</param>
/// <param name="appendIfNotExists">Признак - добавлять параметр если не существует</param>
/// <returns></returns>
bool SetValue(Message message, string xpathTo, object value, bool appendIfNotExists = true)
/// <summary>
/// Установка параметров по списку свойств
/// </summary>
/// <param name="message">Сообщение</param>
/// <param name="copyProps">Параметры копирования</param>
/// <param name="appendIfNotExists">Признак - добавлять параметр если не существует</param>
/// <returns><c>true</c> операция завершена успешно, <c>false</c> иначе</returns>
bool SetValue(Message message, OwnDictionary<string, OwnList<string>> copyProps, bool appendIfNotExists = true)
/// <summary>
/// Установка параметра по списку свойств
/// </summary>
/// <param name="message">Сообщение</param>
/// <param name="xpathTo">Параметры копирования</param>
/// <param name="xpathExpressionFrom">Набор параметров содержащих значения</param>
/// <param name="appendIfNotExists">Признак - добавлять параметр если не существует</param>
/// <returns><c>true</c> операция завершена успешно, <c>false</c> иначе</returns>
bool SetValue(Message message, string xpathTo, OwnList<string> xpathExpressionFrom, bool appendIfNotExists = true)
/// <summary>
/// Установка свойств по пути
/// </summary>
/// <param name="data">Исходные данные в виде строки XML или JSON</param>
/// <param name="dataType">Тип данных в строке</param>
/// <param name="copyProps">XPath пути свойств для копирования</param>
/// <param name="appendIfNotExists">Признак - создавать свойство если его нет</param>
/// <returns>Полученная строка после установки значения</returns>
string SetValue(string data, MessageBodyType dataType, OwnDictionary<string, object> copyProps, bool appendIfNotExists = true)
/// <summary>
/// Установка свойств по пути
/// </summary>
/// <param name="data">Исходные данные в виде массива байт из строки XML или JSON</param>
/// <param name="dataType">Тип данных в строке</param>
/// <param name="copyProps">XPath пути свойств для копирования</param>
/// <param name="appendIfNotExists">Признак - создавать свойство если его нет</param>
/// <returns>Полученная строка после установки значения</returns>
byte[] SetValue(byte[] data, MessageBodyType dataType, OwnDictionary<string, object> copyProps, bool appendIfNotExists = true)
/// <summary>
/// Установка свойств по пути
/// </summary>
/// <param name="data">Исходные данные в виде строки XML или JSON</param>
/// <param name="dataType">Тип данных в строке</param>
/// <param name="copyProps">XPath пути свойств для копирования</param>
/// <param name="appendIfNotExists">Признак - создавать свойство если его нет</param>
/// <returns></returns>
string SetValue(string data, MessageBodyType dataType, OwnDictionary<string, OwnList<string>> copyProps, bool appendIfNotExists = true)
/// <summary>
/// Установка свойств по пути
/// </summary>
/// <param name="data">Исходные данные в виде массива байт из строки XML или JSON</param>
/// <param name="dataType">Тип данных в строке</param>
/// <param name="copyProps">XPath пути свойств для копирования</param>
/// <param name="appendIfNotExists">Признак - создавать свойство если его нет</param>
/// <returns></returns>
byte[] SetValue(byte[] data, MessageBodyType dataType, OwnDictionary<string, OwnList<string>> copyProps, bool appendIfNotExists = true)

Функции получения значения

/// <summary>
/// Получение значения свойства по xpath
/// </summary>
/// <param name="message">Сообщение</param>
/// <param name="xpath">Путь к параметру</param>
/// <param name="throwErrorIfNotFound">Формировать исключение если параметр не
найден</param>
/// <returns><c>true</c> операция завершена успешно, <c>false</c> иначе</returns>
string GetValue(Message message, string xpath, bool throwErrorIfNotFound = false)
/// <summary>
/// Получение значения свойства из XML или JSON
/// </summary>
/// <param name="data">Строка содержащая XML или JSON</param>
/// <param name="dataType">Тип данных в строке</param>
/// <param name="xpathTo">Путь к свойству</param>
/// <param name="throwErrorIfNotFound">Формировать исключение, если не найдено
свойство</param>
/// <returns></returns>
string GetValue(string data, MessageBodyType dataType, string xpathTo, bool
throwErrorIfNotFound = false)
/// <summary>
/// Получение значения свойства из XML или JSON
/// </summary>
/// <param name="data">Массив байт строки содержащей XML или JSON</param>
/// <param name="dataType">Тип данных в строке</param>
/// <param name="xpathTo">Путь к свойству</param>
/// <param name="throwErrorIfNotFound">Формировать исключение, если не найдено
свойство</param>
/// <returns></returns>
byte[] GetValue(byte[] data, MessageBodyType dataType, string xpathTo, bool
throwErrorIfNotFound = false)

Функции конвертации

string TransformToXML(string data, bool addRoot = false, string rootName = "root")
/// <summary>
/// Функция трансформации XML в JSON
/// </summary>
/// <param name="data">Строка содержащая XML</param>
/// <returns></returns>

Примечание

Для использования метода TransformToXML тип данных, который требуется преобразовать в XML, должен иметь корневое поле для всех остальных полей. Корневым полем является сложное поле, которое будет содержать остальные поля, например:

../_images/complex_field.png

С версии 3.1.2.0 функция может использоваться без корневого поля в типе данных. Например:

UserModuleUtils.TransformToXML(Объект.ToString(), true, "КорневойЭлемент");

Пример использования в программном модуле UserModule

//Копирование свойств по пути с созданием свойства назначения если нет
public static void CopyNameProp(Message message){
//Ищем в свойстве name
var xpathFrom="name";
//Копируем в friends/name
var xpathTo="friends[0]/name";
//Скопирует значени свойства, если свойства
//источника xpathFrom нет, копирование не производится
//если нет назначения xpathTo то создается свойство и в него копируется значение
UserModuleUtils.CopyTo(message,xpathFrom,xpathTo);
}
//Копирование свойств по пути с созданием свойства назначения если нет
public static void CopyNameProps(Message message){
var propsList=new OwnDictionary<string, OwnList<string>> {
{"name",new OwnList<string> {"friends[0]/name"}},
{"name",new OwnList<string> {"second-name"}},
{"name",new OwnList<string> {"fill-name"}},
};
//Скопирует значени свойства, если свойства
//источника xpathFrom нет, копирование не производится
//если нет назначения xpathTo то создается свойство и в него копируется значение
UserModuleUtils.CopyTo(message,propsList);
}
//Установка свойства
public static void SetValuesProps(Message message){
var propsList=new OwnDictionary<string,object> {
{"name","Иванов"},
{"second-name","Иван"},
{"fill-name","Иванович"}
};
//Установит значения для свойств:
//"name":"Иванов"
//"second-name":"Иван"
//"fill-name":"Иванович"
UserModuleUtils.SetValue(message,propsList);
}
public static void SetValueProp(Message message){
//Установит значения для свойств:
//"name":"Иванов"
UserModuleUtils.SetValue(message,"name","Тест");
}
//Установка свойства по формуле
public static void SetValues(Message message){
var propsList=new OwnDictionary<string, OwnList<string>> {
{"name",new OwnList<string>{
"friends[0]/name",
"friends[1]/name",
"friends[2]/name"
}}
};
//Установит значения для свойств:
//"name":"friends[0]/name" + "friends[1]/name" + "friends[2]/name"
UserModuleUtils.SetValue(message,propsList);
}
//Получение значения
public static string GetValues(Message message){
var path="friends[0]/name";
//Вернет значение свойства friends[0]/name
return UserModuleUtils.GetValue(message,path);
}
//Трансформация XML в JSON
public static bool ToJson(Message message){
return UserModuleUtils.BodyXmlToJson(message);
}

Пример использования во входящем трансформаторе функций модуля UserModule

var mess = InitMessage;
var obj = mess.GetBodyAsString();
Logger.Verbose(obj);
if (mess.GetBodyType() == MessageBodyType.JSON) {
    UserModule.CopyNameProp(mess);
    obj = mess.GetBodyAsString();
    Logger.Verbose($ "После копирования friends[0]/name будет \"Dolly Walter\" {obj}");
    UserModule.CopyNameProps(mess);
    obj = mess.GetBodyAsString();
    Logger.Verbose($ "После копирования friends[0]/name будет \"Dolly Walter\", добавятся еще свойства second-name и fill-name с значением \"Dolly Walter\" {obj}");
    UserModule.SetValuesProps(mess);
    obj = mess.GetBodyAsString();
    Logger.Verbose($ "После установки значений свойства name:\"Иванов\" second-name:\"Иван\" fill-name:\"Иванович\" {obj}");
    UserModule.SetValueProp(mess);
    obj = mess.GetBodyAsString();
    Logger.Verbose($ "После установки значений name:\"Тест\" {obj}");
    UserModule.SetValues(mess);
    obj = mess.GetBodyAsString();
    Logger.Verbose($ "После установки значений name:\"Dolly WalterHarris KnightSalazar Decker\" {obj}");
    var value_ = UserModule.GetValues(mess);
    Logger.Verbose($ "Получение значения friends[0]/name {value_}");
} else if (mess.GetBodyType() == MessageBodyType.XML) {
    if (!UserModule.ToJson(mess)) {
        Logger.Info("Ошибка преобразования тела в JSON");
    } else {
        Logger.Info($ "Преобразование тела, было тело {obj} после трансформации{mess.GetBodyAsString()}");
    }
}

Коллекция свойств

Класс PropertiesCollection предназначен для работы со словарем свойств, где ключ - это строка (название свойства), а значение - это само свойство. Свойства могут быть простые и списковые. Простые свойства содержат одно значение указанного типа, списковые - соответственно список значений. Поддерживаются следующие типы свойств:

  • string;

  • int;

  • decimal;

  • bool;

  • DateTime;

  • Guid.

Также для типов int/decimal/bool/DateTime/Guid доступны из варианты с Nullable (int?/decimal?/bool?/DateTime?/Guid?). Чтобы создать переменную типа Коллекция свойств, нужно в ЦН выбрать тип переменной Прочие - Коллекция свойств либо можно вручную в коде алгоритма:

var collection = new PropertiesCollection();

Методы класса PropertiesCollection

Внимание

Во все методы вместо string name можно передавать значение перечисления MessageProperties.

Добавление свойств

//Если такое свойство уже есть - то ничего не произойдет
void AddValue<T>(string name, T value)
AddValueList<T>(string name, OwnList<T> valueList) //Добавление спискового свойства
//если такое свойство уже есть - перезапишется новым значением
void Set<T>(string name, T value)
void SetValueList<T>(string name, OwnList<T> value)

Получение свойств

T GetValue<T>(string name) //если свойства нет или у него другой тип - будет исключение
bool TryGetValue<T>(string name, out T value) //если свойства нет или у него другой тип - то вернет false, а в value будет значение по умолчанию для этого типа
bool TryGetValueList<T>(string name, out OwnList<T> values)
OwnList<T> GetValueList<T>(string name)

Удаление свойств

void Remove(string name) //если свойство есть - оно будет удалено

Прочие методы

Type GetPropertyType(string name) // Получить тип для свойства сообщения
bool Has(string name) //есть ли такое свойство любого типа
bool Has<T>(string name) //есть ли такое свойство типа Т
bool HasList<T>(string name)//есть ли такое списковое свойство типа Т
bool IsNull(string name) //в значении свойства null?. Если свойства нет - исключение
void Clear() //очищает коллекцию
bool IsDefault // возвращает true, если коллекция пустая
bool IsEqual(PropertiesCollection input) // возвращает true, если коллекции содержат одинаковые свойства
void CopyFrom(PropertiesCollection collection) // копирует свойства из переданной коллекции в текущую. Существующие перезапишутся, те, которых нет в переданной коллекции остаются

Маппинг

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

../_images/image24.png

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

Способ добавления элементов массива (addOption)

Варианты для выбора

Значение

Замена (Replace)

Количество записей в Массиве2 становится равным количеству записей Массива1.

Добавление (Add)

Количество записей в Массиве2 увеличивается на количество записей Массива1.

Способ заполнения элементов массива (параметр fillOption)

Варианты для выбора

Значение

С копированием (AutoMapping)

Содержимое из полей Массива1 копируется в соответствующие поля Массива2.

Без копирования (ManualMapping)

Содержимое соответствующих полей Массива2 остается пустым.

По умолчанию выбраны параметры замена с копированием. Пример того, как эти параметры работают: Дано два массива: Массив1 и Массив2:

../_images/image252.png

Результат сработавшего маппинга из Массива1 в Массив2 в зависимости от настроек:

../_images/image261.png

При маппинге немассив-немассив независимо от выбранных параметров маппинг всегда срабатывает по схеме Replace+AutoMapping.

Обработка архивной очереди

Работа с сообщениями, попавшими в архив, возможна из пользовательского интерфейса в ЦМ, а также программно с помощью шага Сервисный алгоритм в процессах. Исполнение кода сервисного алгоритма выполняется непосредственно на сервере и только с архивами, размещенными в сервисе обработки процессов, в котором выполняется данный алгоритм. Для работы с архивами реализован фасад ArchiveFacade.

Методы фасада ArchiveFacade, доступные в шаге Сервисный алгоритм:

  • Чтение всех сообщений архива, параметр count ограничивает количество записей: OwnList<ArchiveObject> Select(int count = 200)

  • Чтение всех сообщений архива с учетом фильтра filter: OwnList<ArchiveObject> Select(DataStorageFilter filter)

  • Удаление из архива сообщения по переданному id объекта архива для указанного модуля: void Remove(Guid id, Guid moduleId)

  • Удаление из архива объекта архива для указанного модуля: void Remove(ArchiveObject archiveObject, Guid moduleId)

  • Возвращение из архива сообщения в обработку по переданному id объекта архива для указанного модуля. При передаче свойств в параметре prop эти свойства добавляются к свойствам сообщения: void Restore(Guid id, Guid moduleId, PropertiesCollection prop = null)

  • Возвращение из архива объекта для указанного модуля. При передаче свойство в параметре prop эти свойства добавляются к свойствам сообщения: void Restore(ArchiveObject archiveObject, Guid moduleId, PropertiesCollection prop = null)

  • Удаление всех сообщений с фильтром по модулю: void Remove(Guid moduleId)

  • Восстановление всех сообщений с фильтром по модулю: void Restore(Guid moduleId)

  • Удаление всех сообщений с фильтром: void Remove(DataStorageFilter filter)

  • Восстановление всех сообщений с фильтром: void Restore(DataStorageFilter filter)

Для работы с методами фасада ArchiveFacade реализованы вспомогательные классы:

  • ArchiveObject: запись архива, содержит информацию о событии размещения в архиве и исходном сообщении. Поля объекта:

    • Данные записи архива - сообщение либо данные о БП: public RepositoryObject Data

    • Исходное сообщение: public InternalMessage OriginalMessage

    • Идентификатор модуля: public Guid TargetId

    • Источник сообщения: public Guid SourceId

    • Детали, информация об ошибках, описание сообщения: public string Details

    • Дата внесения в архив: public DateTime InsertDate

    • Позиция записи в архиве: public long Position

    • Тип события (public MessageEventType? EventType): Receive, Send, Enqueue, Dequeue, PeekLock, AbandonPeekLock, CompletePeekLock, DefineFunc, Drop, Error, Create, LiveTimeExpired, Transform, TransportError, Delay, Get, TrRecv, TrSend, Sleep, Processing, Start, Finish, StartChild, FinishChild, IntSend, IntReceive, Read, Write, Delete, Query, Archive, ReceiveAck, SendAck, Step, Route, RouteInt, Cancel.

DataStorageFilter: параметры для фильтрации данных архива:

  • public Guid? StreamId

  • public string MessageType

  • public Guid? ProcessId

  • public Guid? TypeId

  • public Guid? InitialId

  • public bool WithSnapshot

  • public string SnapshotId

  • public Guid? QueueId

  • public Guid? SourceId

  • public int Offset

  • public int Count = 200;

  • public DateTime? InsertDateStart

  • public DateTime? InsertDateEnd

  • public DateTime? CreationDateStart

  • public DateTime? CreationDateEnd

  • public Guid? MessageId

  • SourceId - Сервис обработки процессов:

    • public string ModuleName

    • public string Operation

    • public string ProcessName

    • public string TypeName

    • public List<Guid> ModulesIds = new List<Guid>();

    • public List<Guid> ProcessIds = new List<Guid>();

    • public List<Guid> TypeIds = new List<Guid>();

    • public List<string> Operations = new List<string>();

    • public bool WithBody

    • public MessageEventType? EventType

  • Отправитель:

    • public Guid SourceId

    • public string SourceName

    • public List<Guid> SourceIds = new List<Guid>();

Логи выполнения шага Сервисный алгоритм доступны в журнале Сервера.

Примеры использования методов

  • Вывод в лог сервера 10 сообщений:

Результат: система выберет сообщения с самыми ранними датами вставки:

var list = ArchiveFacade.Select(10);
foreach(var l in list) { Logger.Info(l.Data.Id); }
  • Удалить сообщение по идентификатору:

    ArchiveFacade.Remove(Guid.Parse("id сообщения"), Guid.Parse("id модуля"));
    

Примеры использования ArchiveFacade.Restore:

  • Переотправка сообщений из архива:

    Переотправка не более 200 сообщений:

    1. Создать бизнес-процесс для возврата из архива.

    2. Добавить шаг Сервисный алгоритм.

    ArchiveFacade.Restore(Guid.Parse("id банка"));
    

    Переотправка всех сообщений из архива:

    1. Создать объект класса DataStorageFilter с параметром Count = 0.

    2. Передать его в метод Restore фасада ArchiveFacade.

    DataStorageFilter filter = new DataStorageFilter()
    {
            QueueId = Guid.Parse("id банка"),
            Count = 0
    };
    ArchiveFacade.Restore(filter);
    
  • Отправить сообщение обратно в обработку с указанием свойства test:

    var props = new PropertiesCollection();
    props.AddValue("test", 12345);
    ArchiveFacade.Restore(Guid.Parse("id сообщения"), Guid.Parse("id модуля"), props);
    
  • Использование фильтров:

    var t = new DataStorageFilter()
    {
            Count = 100,
            MessageId = Guid.Parse("id модуля"),
            StreamId = Guid.Parse("id сообщения")
    };
    var list = ArchiveFacade.Select(t);
    foreach(var el in list)
    {
            Logger.Info(el.Data.Id);
            Logger.Info(el.OriginalMessage);
            Logger.Info(Encoding.UTF8.GetString(el.OriginalMessage.Body));
    }
    

Правила обработки очередей

Для описания правил обработки очередей используется код C#. При использовании кода система предоставляет следующие возможности:

  • обращение к обрабатываемому сообщению с помощью переменной InitMessage и ее свойствам на вкладке Правило размещения;

  • вызов пользовательских программных модулей;

  • обращение к свойствам очередей, заданных на вкладке Основные, с помощью Queues;

  • использование логгера Logger.

Примечание

Изменение сообщения при размещении в очереди и извлечении из очереди не допускается!

При написании кода доступно обращение к свойствам очередей с помощью Queues:

  • название очереди;

public string Name { get; set; }
  • количество сообщений в очереди;

public int Count { get; set; }
  • размер очереди (находится в разработке);

public int Size { get; set; }
  • последнее добавление сообщения в очередь;

public DateTime LastInsert { get; set; }
  • последнее получение сообщения из очереди.

public DateTime LastTake { get; set; }

В Правиле размещения пользователь устанавливает в переменную Queue очередь, в которую должно быть помещено сообщение. Для написания алгоритма доступно использование свойств переменной InitMessage. Если значение не установлено, сообщение будет размещено в первой очереди списка.

Пример Правила размещения по очередям в зависимости от размера сообщения:

if(InitMessage.BodyLength <= 100*1024 && Queues.Быстрая.Count<100)
{
        Queue=Queues.Срочная; //Сообщение будет размещено в очереди Срочная
}
else
{
        Queue=Queues.Обычная; //Сообщение будет размещено в очереди Обычная
}
// где Срочная и Обычная - Имена очередей в правиле

В Правиле извлечения пользователь устанавливает в переменную Queue очередь, из которой должен быть получен следующий пакет сообщений в обработку. Если значение не установлено, сообщение будет получено в первой очереди списка. При этом, если в установленной очереди сообщений не будет, то система будет выбирать сообщения из следующих очередей, начиная с первой, в порядке списка.

Пример Правила извлечения по очередям в зависимости от количества сообщений в очередях и даты последней выборки:

if (Queues.Срочная.Count > 0) {
    Queue = Queues.Срочная; //Сообщение будет извлечено из очереди Срочная, если она не пустая
} else if (Queues.Большие.Count > 0) {
    if (Queues.Обычная.Count == 0) {
        Queue = Queues.Большие; //Сообщение будет извлечено из очереди Большие, если Обычная очередь пустая
    } else if (Queues.Обычная.LastTake == null ? true :
        (Queues.Обычная.LastTake.Value.AddMinutes(10) < DateTime.Now)) {
        Queue = Queues.Обычная; //Сообщение будет извлечено из очереди Обычная, если из нее не выбирали более 10 минут
    } else {
        Queue = Queues.Большие;
    }
} else {
    Queue = Queues.Обычная;
}
../_images/image2710.png

Функции конвейера

Полный список функций фасада конвейера:

/// <summary>
/// Добавить сообщение для обработки в конвейер
/// </summary>
/// <param name="message"></param>
/// <param name="conveyorId">Идентификатор конвейера</param>
/// <returns></returns>
public Task Add(Message message, Guid conveyorId);
/// <summary>
/// Добавить сообщение для обработки в конвейер
/// </summary>
/// <param name="message"></param>
/// <param name="conveyorId">Идентификатор конвейера</param>
/// <returns></returns>
public Task Add(InternalMessage message, Guid conveyorId);
/// <summary>
/// Снимок очереди для обработки
/// </summary>
/// <param name="conveyorId">Идентификатор конвейера</param>
/// <returns></returns>
public Task<OwnList<ConveyorProcessData>> GetInputQueueSnapshot(Guid conveyorId);
/// <summary>
/// Текущие оперативные данные конвейера
/// </summary>
/// <param name="conveyorId"></param>
/// <returns></returns>
public Task<OwnList<ConveyorProcessData>> GetOperativeDataSnapshot(Guid
conveyorId);
/// <summary>
/// Результат работы конвейера
/// </summary>
/// <param name="Id">Идентификатор результата</param>
/// <param name="conveyorId">Идентификатор конвейера</param>
/// <returns></returns>
public Task<ConveyorProcessData> GetResult(Guid Id, Guid conveyorId);
/// <summary>
/// Результат работы конвейера
/// </summary>
/// <typeparam name="T">Тип результата</typeparam>
/// <param name="Id">Идентификатор записи</param>
/// <param name="conveyorId">Идентификатор конвейера</param>
/// <returns></returns>
public Task<T> GetResult<T>(Guid Id, Guid conveyorId) where T : BaseClass;
/// <summary>
/// Попытка получить результат операции
/// </summary>
/// <param name="Id">Идентификатор результата</param>
/// <param name="conveyorId">Идентификатор конвейера</param>
/// <param name="result">Результат</param>
/// <returns></returns>
public bool TryGetResult(Guid Id, Guid conveyorId, out ConveyorProcessData result);
/// <summary>
/// Попытка получить результат операции
/// </summary>
/// <typeparam name="T">Тип результата</typeparam>
/// <param name="Id">Идентификатор записи результата</param>
/// <param name="conveyorId">Идентификатор конвейера</param>
/// <param name="result">Результат</param>
/// <returns></returns>
public bool TryGetResult<T>(Guid Id, Guid conveyorId, out T result) where T : BaseClass;
/// <summary>
/// Все результаты работы конвейера
/// </summary>
/// <param name="conveyorId">Идентификатор конвейера</param>
/// <returns></returns>
public Task<OwnList<ConveyorProcessData>> GetConveyorResults(Guid conveyorId);
/// <summary>
/// Все результаты работы конвейера с типизацией
/// </summary>
/// <typeparam name="T">Тип в котором мы хотим получить результат</typeparam>
/// <param name="conveyorId">Идентификатор конвейера</param>
/// <returns></returns>
public Task<OwnList<T>> GetConveyorResults<T>(Guid conveyorId) where T : BaseClass;
/// <summary>
/// Список результатов работы конвейера
/// </summary>
/// <typeparam name="T">Ожидаемый тип данных</typeparam>
/// <param name="conveyorId">Идентификатор конвейера</param>
/// <param name="dataListType">Список, для определения типа данных</param>
/// <returns></returns>
Task<OwnList<T>> GetConveyorResults<T>(Guid conveyorId, OwnList<T> dataListType)
where T : BaseClass;
/// <summary>
/// Удалить результат работы конвейера
/// </summary>
/// <param name="Id">Идентификатор результата</param>
/// <param name="conveyorId">Идентификатор конвейера</param>
/// <returns></returns>
public Task DeleteResult(Guid Id, Guid conveyorId);
/// <summary>
/// Текущий стейт конвейера
/// </summary>
/// <param name="conveyorId">Идентификатор конвейера</param>
/// <returns></returns>
public ApplyState GetState(Guid conveyorId);

Функции Хранилища сообщений

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

  • Запись сообщения и обновление сообщения.

bool Write(Message msg, bool waitResponse, int timeout);

Пример использования в шаге Алгоритм:

MessageStorage.Write(message, true);
  • Проверка существования записи в Хранилище

bool Exists(Guid entityId);

Пример использования в шаге Алгоритм:

MessageStorage.Exists(entityId);
  • Получение сообщения

Message Get(Guid entityId);

Пример использования в шаге Алгоритм:

MessageStorage.Get(entityId);
  • Удаление сообщения

bool Delete(Message msg, bool waitResponse);

Пример использования в шаге Алгоритм:

MessageStorage.Delete(message, true);

Методы трансформации

Доступны следующие объекты:

  • Logger - для вывода данных в лог.

  • Все переменные с вкладки Переменные.

  • Взаимодействие с сервисом хранения учетных данных через объект Credential. Доступны только методы получения данных (Get/Has). (Методы: 7.3.10 Credential).

  • Стандартная переменная OwnList<Metadata.Systems> Receivers - в нее перед выполнением записывается список получателей из переменной типа Сообщение с флагом Принимает сообщение процесса.

  • Методы для задания соответствия сообщений и получателей (можно использовать при необходимости отправить разным получателям сообщения, отличающиеся от исходного).

  • Список сообщений для отправки - доступен через методы /SetMessage/Get. Изначально пустой.

  • Всем получателям исходного сообщения, для которых не было установлено сообщение через SetMessage, будет отправлено оригинальное сообщение:

void SetMessage(Message message)

Если у message есть получатель, которого нет в изначальном списке Receivers - будет исключение. Если этот экземпляр сообщения уже был зарегистрирован - то повторно он не добавляется.

Получение сообщений для определенных получателей (тех, которые были установлены через SetMessage):

OwnList<Message> GetArrayOfMessage(Metadata.Systems rec)
OwnList<Message> GetArrayOfMessage(List<Metadata.Systems> rec)
OwnList<Message> GetArrayOfMessage(string rec)
OwnList<Message> GetArrayOfMessage(List<string> rec)
OwnList<Message> GetArrayOfMessage(Guid rec)
OwnList<Message> GetArrayOfMessage(List<Guid> rec)

Пример скрипта исходящей трансформации:

Logger.Verbose(Сообщение);
// Сообщение.SetBody("wewe");
BaseClass body = Сообщение.GetBodyAsDataType();
switch (body) {
case Номенклатура исходное: {
        foreach(var rec in Receivers) {
            Message m = new Message();
            switch (rec.Name) {
            case "warehouse": {
                    SM.nomenclature newbody = new SM.nomenclature();
                    newbody.descr = исходное.Название;
                    newbody.extKey = исходное.EntityId;
                    //m.SetBody(newbody);
                    Сообщение.SetBody(newbody);
                    break;
                }
            case "Trade": {
                    SM.products newbody = new SM.products();
                    newbody.fullname = исходное.Название;
                    newbody.id = исходное.EntityId;
                    //m.SetBody(newbody);
                    Сообщение.SetBody(newbody);
                    break;
                }
            default:
                continue;
            }
            //m.Receivers.Add(rec);
            //SetMessage(m);
        }
        break;
    }
case null:
    break;
default:
    break;
}
Logger.Verbose($ "После трансформации: {Сообщение}");

Список методов для процессов и алгоритмов входящей и исходящей трансформаций:

void SetOutMessage(Message message)

Например:

SetOutMessage(BaseClass message);
SetOutMessage(string message);
SetOutMessage(byte[] message);

Список методов для скрипта трансформации:

void SetMessage(Message message)

Проверка

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

Функция доступна для следующих элементов:

  • Обработчики

  • Определение функции

  • Скрипты трансформаций

  • Программные модули

  • Функции

  • Алгоритмы процессов

Метод проверки:

bool Check(out CheckResult сheckResult)

Пример выполнения проверки:

  1. Создайте функцию для выполнения проверки:

    ../_images/check2.png

    Код функции:

    if (переменная=="падаю в ошибку")
    {
            throw new Exception("упала на проверке строки");
    }
    
  2. Создайте обработчик для вызова функции:

    ../_images/check4.png
    ../_images/check5.png

    Код обработчика:

    bool res0 = ТипStringСПроверкой.Check(out CheckResult checkResult0);
    Logger.Debug($"Ввели = {ТипStringСПроверкой.Строка}: {checkResult0}");
    if (res0==false)
    {
            throw new Exception($"Корень = {res0}: {checkResult0}");
    }
    
  3. Привяжите обработчик к внешней системе.

  4. Установите флаг Проверка на вкладке Структура типа данных:

    ../_images/check1.png
  5. Нажмите на кнопку Выбор функции для проверки и выберите функцию:

    ../_images/check3.png

    Запрос со строкой, не проходящей проверку, будет завершаться ошибкой:

    ../_images/check6.png

    Запрос со строкой, проходящей проверку, будет успешно обработан:

    ../_images/check7.png

сheckResult представляет собой класс, содержащий ключ имени поля (string) и соответствующий текст ошибок. Для одного поля может быть выбрано несколько функций, т.е. в текст ошибок для поля может быть добавлено несколько ошибок.

Пример алгоритма проверки функции:

Книга кн = new Книга();
кн.Автор = "Стивен Кинг";
bool rez = кн.Check(out CheckResult checkResult);
if (rez)
{
                Logger.Info("Все хорошо");
}
else
{
                Logger.Info($"Все плохо: {checkResult}");
}

Для вызова в пользовательских алгоритмах используется следующая команда:

CustomFunc.[Функция]