2016-01-02 41 views
1

使用BizTalk 2013r2 CU1,我爲入站xsd創建了屬性架構並部署了應用程序。BizTalk - 無法提升屬性

當我使用標準的「xml receive」管道接收到一個示例xml文檔時,我可以看到所需的元素被按照預期提升到上下文中。

然後我創建了一個自定義管道,其中包含「反彙編」階段中的「XML反彙編程序」組件和「驗證」階段中的自定義組件。這個自定義組件需要從上下文中讀取提升的屬性。但是,我發現當我將接收位置從「xml receive」管道切換到自定義管道時,我的屬性沒有得到提升。我用我的自定義組件中下面的代碼寫出來的項目在消息上下文的列表:

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)); 

從事件輸出日誌,我可以看到,某些性能,如消息類型得到了推廣,但我自定義屬性沒有。同樣,如果我將接收位置改回到使用標準的「xml接收」管道,那麼屬性將從同一個xml文檔的副本升級(我通過停止訂閱發送端口並從管理控制檯查看上下文來檢查該屬性)。

我覺得這很奇怪,因爲在相同的(默認)配置下,兩個管道的「反彙編」階段中存在相同的「XML反彙編程序」組件。我開始認爲2013r2CU1可能存在問題 - 是否有其他人遇到過相同的問題?

回答

7

在您的自定義管道中執行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) 
{ 
} 

解決您的問題將在您的自定義組件在「驗證」階段完全讀取流,並把流指針回到一個不太有效的方法到流的開始。

微軟,當你操縱的管道組件消息流的一些準則: https://msdn.microsoft.com/en-us/library/aa577699.aspx

更新:

OP需要消息上下文傳遞給事件處理程序。 有可能使用Lambda表達式: Pass parameter to EventHandler

+0

感謝您的詳細回覆加里,我想你可能是對的。我現在的問題是如何連接它。據我所知,AfterLastReadEvent委託不接受管道上下文 - 我需要能夠訪問。我對代表沒有太多經驗 - 你知道在事件發生時是否可以通過管道上下文嗎? –

+0

@RobBowman是的,有可能。我已經更新了我的答案。我假設你想傳遞消息上下文而不是管道上下文。 –

+0

感謝您的更新加里。對不起,這讓我很長時間,但目前我每天早上只有20分鐘的時間來處理這個問題。你知道一個鏈接到一個EventingReadStream的例子嗎?我一直無法找到一個。在我的「DoSomething」事件中,我現在擁有執行所需映射的代碼。我現在的問題是我不知道如何將其分配迴流。我應該將流作爲ref參數傳遞給事件,那麼對它的任何更新都會使它成爲BizTalk的方式? –

2

你可以做任何你曾經在一個業務流程計劃在驗證階段:

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) 
{ 
} 

這太問題可以通過附加參數爲參考有趣?這會容易得多。

如果不是,這個特定問題的最常見解決方案是一箇中間流水線組件,它強制對流進行完全讀取,儘管從技術上講,您只需要閱讀直到Promoted節點被點擊。

+0

是的,如果我不能使用事件性的閱讀流工作,我可能不得不打破流水線,但我沒有放棄:) :) –

+1

也許只是FYI,但Xml反彙編程序基本上使用事件來編寫屬性本身。你的問題是,直到元素被讀取,相關的事件纔會被觸發。所以,如果你正在嘗試一個事件模型,你可能會陷入與xmldasm相同的地方。 –