【问题标题】:BizTalk - Fail to Promote PropertiesBizTalk - 无法提升属性
【发布时间】:2016-04-06 17:45:01
【问题描述】:

使用 BizTalk 2013r2 CU1,我为我的入站 xsd 创建了一个属性架构并部署了应用程序。

当我使用标准的“xml 接收”管道接收示例 xml 文档时,我可以看到所需的元素已按预期提升到上下文中。

然后我创建了一个自定义管道,其中包含“反汇编”阶段中的“XML 反汇编器”组件和“验证”阶段中的自定义组件。这个自定义组件需要从上下文中读取提升的属性。但是,我发现当我将接收位置从“xml 接收”管道切换到我的自定义管道时,我的属性不会得到提升。我在自定义组件中使用以下代码在消息上下文中写出项目列表:

for (int x = 0; x < contextList.CountProperties; x++)
        {
            contextList.ReadAt(x, out name, out nspace);
            string value = contextList.Read(name, nspace).ToString();
            contextItems += "Name: " + name + " - " + "Namespace: " + nspace + " - " + value + "\r\n";
            if (name == _ContextPropertyName && nspace == _ContextPropertyNamespace)
                promotedPropFound = true;

        }
        Helpers.EventLogHelper eventHelper = new EventLogHelper();
        eventHelper.LogEvent(string.Format("Context items:{0}", contextItems));

        if (promotedPropFound == false)
            throw new Exception(string.Format("Unable to find promoted property with name[{0}] and namespace [{1}]", _ContextPropertyName, _ContextPropertyNamespace));

从事件日志的输出中,我可以看到某些属性(例如 MessageType)已被提升,但我的自定义属性没有。同样,如果我将接收位置改回使用标准的“xml 接收”管道,那么该属性将从同一个 xml 文档的副本中提升(我通过停止订阅发送端口并从管理控制台查看上下文来检查这一点)。

我觉得这很奇怪,因为相同的“XML 反汇编器”组件存在于两个管道的相同“反汇编”阶段,具有相同的(默认)配置。我开始认为 2013r2CU1 可能存在问题 - 有没有其他人遇到过同样的问题?

【问题讨论】:

    标签: biztalk pipeline biztalk-2013r2


    【解决方案1】:

    当 XML 反汇编程序在您的自定义管道中执行时,不能保证您的属性已被提升。

    传入消息以流的形式到达管道,数据指针设置在流的开头。
    我认为 XML Disassembler 不会读取流,它会将其包装到某个流包装器类中,该类将在实际读取流时填充提升的属性。
    该流必须至少被读取一次:当消息被插入消息框时。所以可以保证属性会得到提升,但你不能假设它会在“验证”阶段执行之前完成。

    要确保这确实是您遇到的问题:在将消息导入消息框后检查您的消息。
    如果您的促销属性在那里,那么我所描述的可能就是正在发生的事情。

    解决方案:

    要使您的自定义管道组件正常工作,最好的解决方案是像 XML 反汇编器一样:获取传入流并将其包装到可以触发您需要的任何功能的流包装器类中。

    Microsoft.BizTalk.Streaming.dll 程序集有一些您可能感兴趣的包装类:ForwardOnlyEventingReadStream。
    此类有一个事件 AfterLastReadEvent。您可以创建一些 EventHandler 并让它订阅此事件以仅在完全读取流之后触发您的自定义功能。并且所有属性都已提升。

    您的自定义组件将如下所示:

    public IBaseMessage Execute(IPipelineContext context, IBaseMessage message)
    {
        Stream stream = message.BodyPart.GetOriginalDataStream();
        CForwardOnlyEventingReadStream eventingReadStream = new CForwardOnlyEventingReadStream(stream);
        eventingReadStream.AfterLastReadEvent += new AfterLastReadEventHandler(DoSomething);
    
        message.BodyPart.Data = eventingReadStream; 
        return message;
    }
    
    private static void DoSomething(object src, EventArgs args)
    {
    }
    

    解决问题的效率较低的方法是在“验证”阶段完全读取自定义组件中的流,并将流指针放回流的开头。

    Microsoft 为您在管道组件中操作消息流时提供了一些准则: https://msdn.microsoft.com/en-us/library/aa577699.aspx

    更新:

    OP 需要将消息上下文传递给事件处理程序。 可以使用 Lambda 表达式:

    public IBaseMessage Execute(IPipelineContext context, IBaseMessage message)
    {
        Stream stream = message.BodyPart.GetOriginalDataStream();
        CForwardOnlyEventingReadStream eventingReadStream = new CForwardOnlyEventingReadStream(stream);
        eventingReadStream.AfterLastReadEvent += new AfterLastReadEventHandler((src, args) => DoSomething(src, args, message.Context));
    
        message.BodyPart.Data = eventingReadStream; 
        return message;
    }
    
    private static void DoSomething(object src, EventArgs args, IBaseMessageContext messageContext)
    {
    }
    

    这个 SO 问题对于传递附加参数可能很有趣: Pass parameter to EventHandler

    【讨论】:

    • 感谢您的详细回复加里,我认为您可能是对的。我现在的问题是如何连接它。据我所见, AfterLastReadEvent 委托不接受管道上下文 - 我需要能够访问它。我对代表没有太多经验 - 你知道在引发事件时是否可以传递管道上下文?
    • @RobBowman 是的,有可能。我已经更新了我的答案。我假设您想传递消息上下文而不是管道上下文。
    • 感谢加里的更新。抱歉,这花了我这么长时间,但目前我每天早上只有 20 分钟的时间来处理这个问题。您知道指向 EventingReadStream 示例使用的链接吗?我一直找不到。在我的“DoSomething”事件中,我现在有了执行所需地图的代码。我现在的问题是我不知道如何将其分配回流。我是否应该将流作为 ref 参数传递给事件,然后对其进行任何更新都会使其进入 BizTalk?
    • @RobBowman 嗨,Rob。我唯一的例子是在我自己的 sn-ps 库中,使用方法 DoSomething 将“LALA”写入磁盘上的文件......不要认为它会帮助你:) 关于地图或修改消息:你没有之前不要提它,它让我对你想要做什么以及如何帮助你感到困惑。可能值得创建一个包含所有详细信息的新 SO 问题。
    • 嗨,Gary,该组件执行以下操作: 1. 标识 msg 正文中的一个元素,该元素指示应使用哪个映射。 2. 调用传递此元素值的 BRE。 3. BRE 返回地图的强名称。 4 组件执行映射并将转换后的 xml 发布到 msgbox。由于我对第 1 点的问题和识别提升的上下文属性,我目前正在使用 XML 阅读器来查找所需的元素。这是第 1 点,我想更改以便可以使用提升的属性
    【解决方案2】:

    您可以按照您为编排中的验证阶段计划的任何内容进行操作吗?那会容易得多。

    如果不是,这个特定问题的最常见解决方案是一个中间管道组件,它强制对流进行完整读取,但从技术上讲,您只需要读取到提升节点被命中。

    【讨论】:

    • 是的,如果我不能使它与事件读取流一起工作,我可能不得不求助于中断管道流,但我还没有放弃 :)
    • 也许只是仅供参考,但 Xml 反汇编程序本质上是使用事件来编写属性本身。您的问题是,在读取元素之前,相关事件不会触发。因此,如果您尝试使用事件模型,则可能会陷入与 xmldasm 相同的位置。
    猜你喜欢
    • 1970-01-01
    • 2013-12-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多