2

这里'的情况。我有 12 个集成任务序列,每 15 分钟运行一次,其中大多数实际上是从 oracle 服务器读取某些内容并将其推送到 Web 服务中。我为 oracle 和 web 服务创建了一个端口,并创建了一个主编排,它每 15 分钟循环一次,并调用将执行其任务的其他编排。

现在,我的问题是这些编排不是由消息到达调用的,我需要构建一个将发送到 oracle 端口的消息。看起来像这样的一个:

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

我知道节点值是什么,但我不知道如何构造消息,除了使用“魔术字符串”和连接字符串,我将使用 LoadXml 加载到 xmlDoc 中,然后将其分配给我非常喜欢的消息参数避免出于很多原因(从将来更改命名空间开始)。有没有办法让编排创建我将填写的“空白”消息?

也许问题很简单,我看不到森林里的树,但是我在网上看到的所有示例都被简化了(意味着有人只是将准备好的 xml 放在监视的文件夹中以调用编排)并且不帮助我.

4

4 回答 4

2

这是我为类似问题实现的解决方案:正如 Hugh 建议的那样,我使用从 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 可以通过反射加载它。

<?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>

编排变量和消息

你需要声明

  • `Acme.QueryValues` 类型的变量 *queryValues*
  • `Acme.ResourceXmlDocument` 类型的变量 *resourceXmlDoc*
  • `MySchemaType` 类型的消息

将其放在消息分配形状中

在构造消息形状中创建 MySchemaType 类型的消息 MyRequest

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;

我保存在一个 util lib 中,ResourceXmlDocumentQueryValues从我需要的任何 BizTalk 项目中引用它。各种 Xml 模板文档嵌入到各自的 BizTalk 程序集中。

由 OP 编辑​​:实际上,我进行这项工作的唯一方法是使用 OuterXml 的自定义序列化来实现和持久化消息ISerializableResourceXmlDocument基础中的 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);
    }
于 2012-02-01T15:14:11.810 回答
2

创建一个返回 XmlDocument 类型的静态帮助函数。从您的分配形状中调用此函数。

在辅助函数中,您可以从配置或文本文件加载设置(命名空间等,甚至是完整消息)。

为了获得最佳实践,您应该将此配置存储在 SSO 中。如果您需要这方面的帮助,请告诉我。

于 2012-02-01T14:36:53.850 回答
1

Yossi Dahan在这里比较了这些方法(映射、分配和使用未记录的 API)

API 方法使用 Microsoft.BizTalk.Component.Interop.DocumentSpec -在此处此处参考,但正如 Yossi 所提到的,它比地图或 XmlDocument.LoadXml 慢得多

只是一些使用说明:

  • 程序集为TestSchema,Version=1.0.0.0,Culture=neutral,publicKeyToken=xxxxxxxxxxxxxxxx”;
  • schemaName 是 TestSchema.MyTestSchema[+myRootNode1]
  • 注意是版本相关的 - 如果程序集版本更改,则创建将失败,除非也更新版本字符串。
  • 以这种方式创建的新消息不一定对 XSD 有效。例如 DateTimes 和 Ints 将只是空元素,即使它们是可空的(这不会在 XML 中设置 nillable=true)
于 2012-02-01T15:22:01.557 回答
0

您是否考虑过使用转换形状来创建要发送到 ORACLE 的架构实例?

这是在消息分配形状中创建消息的一种替代方法。如果您需要更多详细信息,请告诉我!

高温高压

于 2012-02-01T14:01:55.767 回答