【问题标题】:Referencing a port in an orchestration via a string variable通过字符串变量引用编排中的端口
【发布时间】:2012-05-28 00:23:04
【问题描述】:

我正在尝试开发用于配置动态端口的通用 BizTalk 应用程序。我有一个编排,可以拉回每个端口的所有配置设置,我想遍历这些设置并配置端口。设置保存在 MSSQL 中,例如,其中两个属性是 PortName 和 Address。因此,在编排中,我想通过字符串变量 PortName 引用端口。那么有没有办法获取编排中所有端口的集合或通过字符串变量引用端口,即Port['MyPortName'](Microsoft.XLANGs.BaseTypes.Address) = "file://c:\test\out\%MessageId%.xml"Thanks

【问题讨论】:

  • 我意识到我没有严格回答您的问题,而是表明在传出消息的上下文中动态应用端口设置。这是等式的第二部分。我将尝试弄清楚如何将端口作为字符串引用并在下面改进我的答案。

标签: biztalk biztalk-2010 orchestration


【解决方案1】:

首先,您不应该尝试使用 Orchestration 进行这样的配置更改。从技术上讲,做您想做的事情是可行的,但作为一种做法,您不应该将业务流程与管理混为一谈。

执行此类操作的最佳方法是编写一些普通脚本或 PowerShell。

为了回答你的问题,你可以从 ExplorerOM 的 BtsOrchestration 类中获取你想要的数据 http://msdn.microsoft.com/en-us/library/microsoft.biztalk.explorerom.btsorchestration_members(v=bts.20)

【讨论】:

  • 感谢您提供的信息,很遗憾您发送的链接无效。但是,我已经将 ExplorerOM 视为一种可能的解决方案。你能解释一下为什么我不应该通过编排设置动态端口吗?我们通常在运行时从 SSO 中拉回此类设置,但是如果需要更改它们,则必须重新启动主机实例,而从 SQL 中拉回它们意味着可以随时重新配置它们。我现在要做的是让流程更通用,可以从任何 BT 应用程序调用。
【解决方案2】:

为了从编排中动态配置动态逻辑发送端口,必须将设置存储到持久数据存储(例如数据库或配置文件)中,并实现一种在运行时动态分配这些属性的方法。

但首先,我们需要了解配置动态发送端口时发生了什么。

如何配置动态逻辑发送端口

来自编排内部的Configuring the properties of a dynamic logical send port 涉及两个步骤:

  • 首先,必须在发送端口上指定TransportType 和目标Address 属性。这通常在 Expression Shape 中完成,代码类似于:

    DynamicSendPort(Microsoft.XLANGs.BaseTypes.TransportType) = "FILE"; DynamicSendPort(Microsoft.XLANGs.BaseTypes.Address) = "C:\Temp\Folder\%SourceFileName%";

  • 其次,必须在传出消息本身的上下文中指定任何其他传输属性。几乎所有 BizTalk 适配器都有additional properties,用于消息引擎和 XLANG/s 编排引擎之间的通信。例如,ReceivedFileName 上下文属性用于动态设置特定名称,以便 FILE 适配器何时将传出消息保存在其目标位置。这最好在 Assignment Shape 内执行,作为构建传出消息的一部分:

    OutgoingMessage(FILE.ReceiveFileName) = "HardCodedFileName.xml"

您会注意到,大多数配置属性必须在传出消息的上下文中指定,指定名称空间前缀(例如 FILE)、属性名称(例如 ReceiveFileName)以及显然分配给相应消息的值属性。

实际上,所有上下文属性都是存在于众所周知 Microsoft.BizTalk.GlobalPropertySchemas.dll 程序集内的类。这可以通过在 Visual Studio 的对象资源管理器中查找此程序集来确认。

尽管配置动态逻辑发送端口所需的大多数上下文属性都存在于此特定程序集中,但并非所有属性都存在。例如,MSMQ BizTalk 适配器使用单独的程序集来存储其上下文属性。显然,第三方或自定义适配器也带有附加程序集。

因此,为了使用如下所述的灵活方法在动态发送端口上设置上下文属性,需要四个信息:

  • 包含上下文属性类的程序集的完全限定名称。
  • 命名空间前缀。
  • 属性名称。
  • 属性值。

在持久媒体中存储端口设置

以下 .XSD 架构说明了一种用于序列化端口设置的可能结构。

一旦序列化,指定的上下文属性就可以很容易地存储在 SQL 数据库或配置文件中。例如,以下是本文中用作示例的设置:

配置动态逻辑发送端口的灵活方法

使用简单的帮助程序库,设置动态端口配置非常容易。首先,您必须从持久性介质中检索序列化设置。这可以使用 WCF-SQL 适配器和一个简单的存储过程轻松实现。

一旦检索到这些属性,就可以将这些属性反序列化为强类型 C# 对象图。为此,首先使用以下命令行实用程序创建上面显示的 ContextProperties 模式的 C# 表示:

xsd.exe /classes /language:cs /namespace:Helper.Schemas .\ContextProperties.xsd

这会生成一个部分类,可以使用以下方法进行改进:

namespace Helper.Schemas
{
    public partial class ContextProperties
    {
        public static ContextProperties Deserialize(string text)
        {
            using (MemoryStream stream = new MemoryStream())
            {
                byte[] buffer = Encoding.UTF8.GetBytes(text);
                stream.Write(buffer, 0, buffer.Length);
                stream.Seek(0, SeekOrigin.Begin);
                return (ContextProperties) 
                    Deserialize(
                          stream
                        , typeof(ContextProperties));
            }
        }

        public static Object Deserialize(Stream stream, Type type)
        {
            XmlSerializer xmlSerializer = new XmlSerializer(type);
            return xmlSerializer.Deserialize(stream);
        }
    }
}

其次,应用此配置涉及从代码创建 XLANG/s 消息,并根据反序列化的 ContextProperties 对象图中指定的上下文属性类的描述,使用反射动态设置上下文属性。

为此,我使用了从Paolo Salvatori 的系列文章regarding dynamic transformations 中借用的技术,该技术包括创建一个自定义的BTXMessage 派生类,由BizTalk XLANG/s 引擎在内部使用。

namespace Helper.Schemas
{
    using Microsoft.BizTalk.XLANGs.BTXEngine; // Found in Microsoft.XLANGs.BizTalk.Engine
    using Microsoft.XLANGs.Core; // Found in Microsoft.XLANGs.Engine

    [Serializable]
    public sealed class CustomBTXMessage : BTXMessage
    {
        public CustomBTXMessage(string messageName, Context context)
            : base(messageName, context)
        {
            context.RefMessage(this);
        }

        public void SetContextProperty(string assembly, string ns, string name, object value)
        {
            if (String.IsNullOrEmpty(ns))
                ns = "Microsoft.XLANGs.BaseTypes";
            if (String.IsNullOrEmpty(assembly))
                assembly = "Microsoft.BizTalk.GlobalPropertySchemas";

            StringBuilder assemblyQualifiedName = new StringBuilder();
            assemblyQualifiedName.AppendFormat("{0}.{1}, {2}", ns, name, assembly);

            Type type = Type.GetType(assemblyQualifiedName.ToString(), true, true);
            SetContextProperty(type, value);
        }

        internal void SetContextProperty(string property, object value)
        {
            int index = property.IndexOf('.');
            if (index != -1)
                SetContextProperty(String.Empty, property.Substring(0, index), property.Substring(index + 1), value);
            else
                SetContextProperty(String.Empty, String.Empty, property, value);
        }

    }
}

现在,难题的最后一部分是如何在 Orchestration 中使用这个自定义类。这可以使用以下帮助代码在 Assignment Shape 中轻松完成:

namespace Helper.Schemas
{
    using Microsoft.XLANGs.BaseTypes;
    using Microsoft.XLANGs.Core; // Found in Microsoft.XLANGs.Engine

    public static class Message
    {
        public static XLANGMessage SetContext(XLANGMessage message, ContextProperties properties)
        {
            try
            {
                // create a new XLANGMessage

                CustomBTXMessage customBTXMessage = new CustomBTXMessage(message.Name, Service.RootService.XlangStore.OwningContext);

                // add parts of the original message to it

                for (int index = 0; index < message.Count; index++)
                    customBTXMessage.AddPart(message[index]);

                // set the specified context properties

                foreach (ContextPropertiesContextProperty property in properties.ContextProperty)
                    customBTXMessage.SetContextProperty(property.assembly, property.@namespace, property.name, property.Value);

                return customBTXMessage.GetMessageWrapperForUserCode();
            }

            finally
            {
                message.Dispose();
            }
        }
    }
}

您可以在 Assignment Shape 中使用此静态方法,如下面所示的代码,其中OutboundMessage 表示您要设置上下文的消息:

OutboundMessage = Helper.Schemas.Message.SetContext(OutboundMessage, contextProperties);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2010-12-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-11-14
    • 1970-01-01
    • 2017-11-04
    • 2021-10-02
    相关资源
    最近更新 更多