Построение сообщения вручную внутри оркестровки - PullRequest
2 голосов
/ 01 февраля 2012

Здесь 'ситуация. У меня есть последовательность из 12 интеграционных задач, которые нужно запускать каждые 15 минут, большинство из них на самом деле читают что-то с сервера оракула и помещают его в веб-сервис. Я создал порт как для оракула, так и для веб-службы, и создал главную оркестровку, которая зацикливается каждые 15 минут и вызывает другие оркестровки, которые будут выполнять свои задачи.

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

<Select xmlns="http://Microsoft.LobServices.OracleDB/2007/03/HR/Table/EMPLOYEES">
    <COLUMN_NAMES>*</COLUMN_NAMES>
    <FILTER>DATE=somedate</FILTER>
</Select>

Я знаю, какими будут значения узла, но я не знаю, как создать сообщение, кроме как использовать «волшебные строки» и конкатенацию строк, которые я загружу в xmlDoc с помощью LoadXml, а затем назначу это параметрам сообщения, которые я бы очень хотелось бы избежать по многим причинам (начиная с изменения в пространстве имен в будущем). Есть ли способ для оркестровки создать «пустое» сообщение, которое я потом заполню?

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

Ответы [ 4 ]

2 голосов
/ 01 февраля 2012

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

Внутри вспомогательной функции вы можете загрузить настройки (пространство имен и т. Д. Или даже полное сообщение) из файла конфигурации или текстового файла.

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

2 голосов
/ 01 февраля 2012

Вот решение, которое я реализовал для аналогичной проблемы: как предлагает Хью, я использую помощник, унаследованный от XmlDocument.

Класс шаблонов XML

using System;
using System.Globalization;
using System.IO;
using System.Reflection;
using System.Xml;

namespace Acme
{
    [Serializable]
    public class ResourceXmlDocument : XmlDocument
    {
        public ResourceXmlDocument(Type assemblyType, string resourceName, QueryValues queryValues)
        {
            try
            {
                Assembly callingAssembly = Assembly.GetAssembly(assemblyType);

                if (null == callingAssembly)
                {
                    throw new ResourceException("GetExecutingAssembly returned null");
                }

                Stream resourceStream = callingAssembly.GetManifestResourceStream(resourceName);

                Load(resourceStream);

                if (null == queryValues)
                {
                    throw new ResourceException("queryValues not initialized");
                }

                if (queryValues.Keys.Count < 1)
                {
                    throw new ResourceException("queryValues.Keys must have at least one value");
                }


                foreach (string querycondition in queryValues.Keys)
                {
                    XmlNode conditionNode = this.SelectSingleNode(querycondition);

                    if (null == conditionNode)
                    {
                        throw new ResourceException(string.Format(CultureInfo.InvariantCulture, "Condition: '{0}' did not return a XmlNode", querycondition));
                    }

                    XmlAttribute valueAttribute = conditionNode.Attributes["value"];

                    if (null == valueAttribute)
                    {
                        throw new ResourceException(string.Format(CultureInfo.InvariantCulture, "Condition: '{0}' with attribute 'value' did not return an XmlAttribute ", querycondition));
                    }

                    valueAttribute.Value = queryValues[querycondition];
                }
            }
            catch (Exception ex)
            {
                throw new ResourceException(ex.Message);
            }
        }
    }
}

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

Вспомогательный класс QueryValues ​​

using System;
using System.Collections.Generic;
using System.Runtime.Serialization;

namespace Acme
{
    [Serializable]
    public class QueryValues : Dictionary<string, string>
    {
        public QueryValues()
        {
        }


        protected QueryValues(SerializationInfo info, StreamingContext context) : base(info, context)
        {
        }
    }
}

Шаблон XML

Добавьте документ Xml MyTemplate.xml в свой проект и измените действие компиляции на Embedded Resource, чтобы ResorceXmlDocument мог загрузить его через Reflection.

<?xml version="1.0" encoding="utf-8" ?>
<root>
    <SomeOtherNode>some (fixed) value</SomeOtherNode>
    <MyNodeName tablename="MyTableName" fieldname="MyFieldName" value="0" />
    <YetAnotherNode>
        <SubNode>Foo</SubNode>
    </YetAnotherNode>
</root>

Переменные и сообщения оркестровки

Вам нужно будет объявить

  • переменная * queryValues ​​* типа `Acme.QueryValues`
  • переменная * resourceXmlDoc * типа `Acme.ResourceXmlDocument`
  • сообщение типа `MySchemaType`

Собираем его вместе в форме назначения сообщения

внутри формы сообщения Construct, создающей сообщение MyRequest типа MySchemaType

queryValues = new Acme.QueryValues();

queryValues.Add("//MyNodeName[@tablename='MyTableName' and @fieldname='MyFieldName']", "MyValueToSet");

resourceXmlDoc = new Acme.ResourceXmlDocument(typeof(Acme.MySchemaType), "MyTemplate.xml", queryValues);

MyRequest = resourceXmlDoc;

Я храню ResourceXmlDocument и QueryValues в утилите lib и ссылаюсь на нее из любого проекта BizTalk, который мне нужен. Различные документы шаблона Xml встроены в соответствующую сборку BizTalk.

РЕДАКТИРОВАТЬ с помощью OP: На самом деле единственный способ, с помощью которого я работаю, это также реализовать ISerializable на ResourceXmlDocument и сохранить сообщение, используя пользовательскую сериализацию OuterXml. XmlDocument в базе просто не сериализуем сам по себе. Если есть другой подход, не стесняйтесь редактировать это.

[Serializable]
public class ResourceXmlDocument : XmlDocument, ISerializable
{

    ...

    protected ResourceXmlDocument(SerializationInfo info, StreamingContext context)
    {
        if (info == null) throw new System.ArgumentNullException("info");
        Load(info.GetString("content"));
    }


    void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context)
    {
        if (info == null) throw new System.ArgumentNullException("info");
        info.AddValue("content", this.OuterXml);
    }
1 голос
/ 01 февраля 2012

Йосси Дахан сравнивает эти методы (сопоставление, назначение и использование недокументированного API) здесь

Метод API использует Microsoft.BizTalk.Component.Interop.DocumentSpec - ссылки здесь и здесь , но, как упоминает Йосси, намного медленнее, чем карты или XmlDocument.LoadXml

Несколько замечаний по использованию:

  • Assembly is TestSchema, версия = 1.0.0.0, культура = нейтральная, publicKeyToken = xxxxxxxxxxxxxxxx ”;
  • имя-схемы - TestSchema.MyTestSchema [+ myRootNode1]
  • Примечание зависит от версии - если версия сборки изменяется, создание не будет выполнено, если также не будет обновлена ​​строка версии.
  • Новое сообщение, созданное таким образом, не обязательно действует в отношении XSD. например DateTimes и Ints будут просто пустыми элементами, даже если они с нулем (и это не установит nillable = true в XML)
0 голосов
/ 01 февраля 2012

Рассматривали ли вы использование формы преобразования для создания экземпляра схемы, которую вы хотите отправить в ORACLE?

Это одна из альтернатив создания сообщения в форме «Назначение сообщения». Дайте мне знать, если вам требуется больше деталей!

НТН

...