Поделиться через


Расширение Universal Resource Scheduling с использованием универсального языка FetchXML

UFX является расширенным языком запросов, который позволяет запросить данные с использование динамического языка FetchXM, формировать и подготовить получающиеся в результате данные для потребления решением Universal Resource Scheduling (URS). Этот язык запросов позволяет создавать настраиваемые запросы для настройки и расширения фильтров доски расписания и помощника по расписанию для удовлетворения уникальных бизнес-целей организации.

UFX состоит из двух компонентов: сумка UFX и запрос UFX.

Простая сумка UFX

Сумка UFX содержит определенные статические типизованные данные. В памяти она представляла как словарь с ключами и значениями. Ее можно сериализовать в JSON и XML. Типизованные данные позволяют запросу UFX запрашивать данные из него, а клиенту интерфейса пользователя задавать привязку к нему.

По практическим причинам и причинам производительности сумка в памяти реализована на основе объекта Entity пакета SDK приложений Dynamics 365.

Пример сумки, содержащей два значения.

В памяти:

key значение тип
name Иван строка
возраст 36 целое

В JSON:

{
    "name": "John",
    "age": 36
}

В XML:

<bag>
    <name ufx-type="string">John</name>
    <age ufx-type="int">36</age>
</bag>

Типы, поддерживаемые UFX

Сумка UFX может содержать значения со многими типами. Они организованы в три класса типов:

Категория значение
Простые типы bool (Boolean), int (Int32), long (Int64), double (Double), decimal (Decimal), datetime (DateTime), guid (Guid), string (String)
Простые типы, специфичные для Dynamics 365: money (Money), option (OptionSet), lookup (EntityReference)
Другие сумки bag (Entity)
Список сумок list (EntityCollection)

Вот пример сумки JSON, содержащей больше типов:

{
    "citizen": true,          // implicit bool
    
    "age": 36,                // explicit int
    "age@ufx-type": "int",

    "name": {                 // nested bag
        "first": "John",
        "last": "Doe"
    },

    "children": [             // list of bags
        { "name": "Sam" },
        { "name": "Judy" }
    ]
}

Такая же сумка в XML:

<bag>
    <citizen ufx-type="bool">true</citizen>

    <age ufx-type="int">36</age>

    <name ufx-type="bag">
        <first ufx-type="string">John</first>
        <last ufx-type="string">Doe</last>
    </name>

    <children ufx-type="list">
        <bag>
            <name ufx-type="string">Sam</name>
        </bag>
        <bag>
            <name ufx-type="string">Judy</name>
        </bag>
    </children>
</bag>

Введение в запросы UFX

Запросы UFX записываются как сумки UFX на основе XML. Свойства в сумке могут содержать директивы UFX для динамического запроса данных. Запрос UFX выполняется на объектах в памяти, а не в XML. Только директивы записываются в XML. Их выходные данные можно сериализовывать в JSON или XML.

Следующий запрос UFX определяет свойство accounts в сумке с директивой UFX source. Это приводит к исполнению встроенного языка FetchXML в Dynamics 365, и свойство accounts становится списком сумок, или EntityCollection, при этом каждая сумка является экземпляром записи организации из Dynamics 365.

<bag xmlns:ufx="https://schemas.microsoft.com/dynamics/2017/universalfetchxml">
    <accounts ufx:source="fetch">
        <fetch top="10">
            <entity name="account" />
        </fetch>
    </accounts>
</bag>

Запрос UFX обрабатывается последовательно и может содержать много запросов языка FetchXML.

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

<bag>
  <accounts ufx-type="list">
    <bag ufx-id="166e39dd-34a1-e611-8111-00155d652f01" ufx-logicalname="account">
      <accountid ufx-type="guid">166e39dd-34a1-e611-8111-00155d652f01</accountid>
      <accountnumber ufx-type="string">ABSS4G45</accountnumber>
      <name ufx-type="string">Fourth Coffee (sample)</name>
      <statecode ufx-type="option" ufx-formatvalue="Active">0</statecode>
      <websiteurl ufx-type="string">https://www.fourthcoffee.com/</websiteurl>
      <primarycontactid ufx-type="lookup" ufx-formatvalue="Yvonne McKay (sample)" ufx-logicalname="contact">7c6e39dd-34a1-e611-8111-00155d652f01</primarycontactid>
      ...
    </bag>
    <bag ufx-type="bag" ufx-id="186e39dd-34a1-e611-8111-00155d652f01" ufx-logicalname="account">
      <accountid ufx-type="guid">186e39dd-34a1-e611-8111-00155d652f01</accountid>
      <accountnumber ufx-type="string">ACTBBDC3</accountnumber>
      <name ufx-type="string">Litware, Inc. (sample)</name>
      <statecode ufx-type="option" ufx-formatvalue="Active">0</statecode>
      <websiteurl ufx-type="string">https://www.litwareinc.com/</websiteurl>
      <primarycontactid ufx-type="lookup" ufx-formatvalue="Susanna Stubberod (sample)" ufx-logicalname="contact">7e6e39dd-34a1-e611-8111-00155d652f01</primarycontactid>
      ...
    </bag>
    ...
  </accounts>
</bag>

Директива UFX select принимает выражение XPath, которое выбирает значения из текущей сумки.

<bag xmlns:ufx="https://schemas.microsoft.com/dynamics/2017/universalfetchxml">
    <accounts ufx:source="fetch">
        <fetch top="10">
            <entity name="account" />
        </fetch>
    </accounts>

    <first_account_name ufx:select="accounts/bag[1]/name" />

    <!-- null values remove properties from the bag -->
    <accounts ufx:select="$null" />
</bag>

Получающаяся сумка в XML:

<bag>
    <first_account_name ufx-type="string">Fourth Coffee (sample)</first_acount_name>
</bag>

Определенно самым мощным аспектом запроса UFX является возможность динамически формировать FetchXML на основании введенных данных.

В примере ниже мы ищем организации по значению, указанному пользователем и доступному в виде сумки UFX через переменную XPath $input. Обратите внимание на директивы UFX if и value в элементе condition.

<bag xmlns:ufx="https://schemas.microsoft.com/dynamics/2017/universalfetchxml">
    <accounts ufx:source="fetch">
        <fetch top="10">
            <entity name="account">
                <filter>
                    <condition attribute="name" operator="like" ufx:if="$input/NameFilter">
                        <ufx:value select="$input/NameFilter" attribute="value" />
                    </condition>
                </filter>
            </entity>
        </fetch>
    </accounts>
</bag>

Если свойство NameFilter во входящей сумке содержало %city%, получаемое условие FetchXML, выполняемое Dynamics 365, будет выглядеть следующим образом.

<condition attribute="name" operator="like" value="%city%" />

Ключи, значения и метаданные

Сумка UFX содержит ключи и значения, при этом некоторые значения имеют дополнительные метаданные, дополнительно описывающие их.

Примером может быть значение типа lookup (EntityReference). При запросе из Dynamics 365 с помощью языка FetchXML он вернет логическое имя сущности, а также форматированное отображаемое имя записи. Сумка UFX сохраняет эти дополнительные сведения в виде метаданных, прикрепленных к основному значению.

При сериализации в JSON lookup с метаданными выглядит следующим образом:

{
    "primarycontactid": "7e6e39dd-34a1-e611-8111-00155d652f01",
    "primarycontactid@ufx-type": "lookup",
    "primarycontactid@ufx-logicalname": "contact",
    "primarycontactid@ufx-formatvalue": "Susanna Stubberod (sample)"
}

В XML:

<primarycontactid ufx-type="lookup" ufx-formatvalue="Susanna Stubberod (sample)" ufx-logicalname="contact">7e6e39dd-34a1-e611-8111-00155d652f01</primarycontactid>

XPath поверх данных Dynamics 365

Типизованные данные в сумке UFX позволяют запросу UFX видеть их в структурированном формате и использовать директиву XPath для обхода данных и выбора значений из них.

Выражение XPath, указанное в директиве UFX, видит данные в сумке подобно структуре сумки в XML-сериализованной форме. Однако данные сохраняются в объектах .NET в памяти (в случаях типов Entity и EntityCollection), а не в документах XML.

Приложение A. Справочник по типам UFX

Примечание. Все типы UFX поддерживают метаданные ufx-type и ufx-formatvalue. Дополнительные метаданные описаны рядом с каждым типом в таблице ниже.

Имя UFX Код типа атрибута Имя .NET Метаданные UFX
bool Логическое Логическое
целое Целое число Int32
long BigInt Int64
double Double Double
десятичное Десятичное число Десятичное число
Дата/время Дата и время Дата и время
guid Uniqueidentifier GUID
строка Памятка Строка
деньги Денежная сумма Денежная сумма
option Список выбора OptionSetValue
поиск Поиск EntityReference ufx-logicalname
bag Н/Д Сущность ufx-id
ufx-logicalname
list Н/Д EntityCollection
Н/Д Н/Д AliasedValue ufx-aliasentity
ufx-aliasattribute

Приложение B. Директивы запроса UFX

Директивы UFX могут использоваться в свойствах сумки и элементах XML запроса FetchXML.

Директивы сумки UFX

Атрибут Value Описание
ufx:if XPath Проверяет выражение XPath и обрабатывает свойство только в том случае, если проверка возвращает истинное значение
ufx:source fetch Выполняет встроенный элемент XML <fetch> и назначает результат свойству
ufx:select XPath Выполняет выражение XPath и назначает результат свойству
При запросе bag или list необязательный дочерний элемент bag в форме XML может быть указан для преобразования результата выражения XPath

Директивы UFX FetchXML

Элемент Атрибут Value Описание
Все элементы ufx:if XPath Проверяет выражение XPath и выдает элемент XML только при успешном завершении проверок
ufx:apply select XPath Выполняет циклы по набору узлов, возвращенному выражением XPath, и выводит дочерние XML-элементы по одному разу для каждого узла
ufx:value select XPath Выполняет выражение XPath и выводит результат в текущем элементе XML
ufx:value attribute имя атрибута Назначает результат выражения XPath указанному имени атрибута в текущем элементе XML

Приложение C. Функции UFX XPath

UFX добавляет несколько новых функций помимо функций, доступным изначально в XPath.

datetime()

  • datetime(): возвращает текущее время в формате UTC

list()

  • list(bag | list, ...[bag | list]): принимает ряд значений bag или list в качестве входных данных и преобразует их в один элемент list

lookup-to-list()

  • lookup-to-list(lookup, ...[lookup]): принимает несколько значений lookup, преобразует каждое из них в элемент bag с установленными данными ufx-id и ufx-logicalname, затем преобразует их в один элемент list

option-to-list()

  • option-to-list(option, ...[option]): принимает несколько значений option, преобразует каждое из них в элемент bag с одним свойством option, затем преобразует их в один элемент list

order()

  • order(list, string, bool): упорядочивает список по свойству в каждой сумке. Свойство указывается в аргументе 2, по уменьшению указывается в аргументе 3.
  • order(list, list): упорядочивание списка с несколькими порядками сортировки, указанными как список в аргументе 2. Каждый bag во втором списке может иметь свойство name и descending

iif()

  • iif(любой, любой, любой): если аргумент 1 равен true, возвращается аргумент 2, в противном случае возвращается аргумент 3

Приложение D. Переменные UFX XPath

Имя Описание
$input Элемент bag, доступный в запросе UFX с входными значениями
$null Константа NULL. При выборе $null в свойстве это свойство удаляется из сумки
$current Ссылка на текущую сумку, обрабатываемую запросом UFX

См. также

Общие сведения и настройка сопоставления ресурсов в Universal Resource Scheduling

Заметки о выпуске расширяемости Universal Resource Scheduling