在业务流程中手动构建消息

时间:2012-02-01 11:32:34

标签: oracle11g biztalk biztalk-2010

这里'的情况。 我有一系列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 个答案:

答案 0 :(得分:2)

创建一个返回一种XmlDocument的静态助手函数。从您指定的形状中调用此函数。

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

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

答案 1 :(得分: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);
            }
        }
    }
}

当然,我的expample定位了一个固定属性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 doc 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>

业务流程变量和消息

您需要声明

  • 类型为“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;

我将ResourceXmlDocumentQueryValues保留在util 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);
    }

答案 2 :(得分:1)

Yossi Dahan比较这些方法(映射,分配和使用未记录的API)here

API方法使用Microsoft.BizTalk.Component.Interop.DocumentSpec - 引用herehere,但正如Yossi所提到的,比地图或XmlDocument.LoadXml慢得多

关于用法的一些注释:

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

答案 3 :(得分:0)

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

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

HTH