使用 WCF 通道模型在 SAP 中串流 Flat-File IDOC
Microsoft BizTalk Adapter for mySAP Business Suite 支援 SendIdoc 和 ReceiveIdoc 作業的節點值串流。 這些作業是用來傳送和接收一般檔案 (字串,) IDOC 來回傳送和接收配接器。 在這兩個作業中,整個 IDOC 的資料都包含在單一節點底下的字串中, < (idocData >) 。 針對大型IDOC,在配接器與程式碼之間串流 IDOC 資料可能會節省大量的記憶體資源。
如需配接器如何支援串流的背景資訊,請參閱 串流和 SAP 配接器。 您應該先閱讀本主題,再繼續進行。
本主題中的各節說明當您使用 WCF 通道模型時,如何實作 SendIdoc 和 ReceiveIdoc 作業的節點值串流。
將輸出 Flat-File IDOC 串流至配接器
配接器支援 SendIdoc 作業要求訊息上的節點值串流。
若要在 WCF 通道模型中的 SendIdoc 作業上支援節點值串流,您必須:
實作 System.ServiceModel.Channels.BodyWriter ,其能夠串流 IDOC 資料 (在 IDOC 資料上執行節點值串流) 。
使用 Message.Create 方法的適當多載來提供訊息本文,以建立用來叫用作業的System.ServiceModel.Message。
實作 BodyWriter
下列範例示範執行節點值串流的 BodyWriter 實作。
/// <summary>
/// This class overrides the OnWriteBodyContents function to do node-value streaming
/// </summary>
class StreamingBodyWriter : BodyWriter, IDisposable
{
XmlReader m_reader = null;
int m_chunkSize;
/// <summary>
/// Initializes the body writer
/// </summary>
/// <param name="reader">Reader for input</param>
/// <param name="chunkSize">The chunksize in which the data is passed to adapter</param>
public StreamingBodyWriter(XmlReader reader, int chunkSize)
: base(false)
{
m_reader = reader;
if (chunkSize <= 0)
throw new ApplicationException("ChunkSize should be a positive value");
m_chunkSize = chunkSize;
}
protected override void OnWriteBodyContents(XmlDictionaryWriter writer)
{
if (m_reader == null)
throw new ApplicationException("Reader cannot be null");
while (m_reader.Read())
{
switch (m_reader.NodeType)
{
case XmlNodeType.Element:
writer.WriteStartElement(m_reader.LocalName, m_reader.NamespaceURI);
break;
case XmlNodeType.Text:
#region Streaming Code
char[] tempBuffer = new char[m_chunkSize];
int length = 0;
while ((length = m_reader.ReadValueChunk(tempBuffer, 0, m_chunkSize)) > 0)
{
writer.WriteString(new String(tempBuffer, 0, length));
}
#endregion
break;
case XmlNodeType.EndElement:
writer.WriteEndElement();
break;
}
}
}
#region IDisposable Members
public void Dispose()
{
if (m_reader != null)
{
m_reader.Close();
m_reader = null;
}
}
#endregion
}
使用 BodyWriter 建立訊息
下列範例示範如何使用上述範例中的 BodyWriter 建立 SendIdoc 要求訊息。 訊息資料是從檔案讀取。
XmlReader readerIn = XmlReader.Create ("sendidoc.xml");
// StreamingBodyWrtier class is responsible for streaming
StreamingBodyWriter stBW = new StreamingBodyWriter(readerIn, chunkSize);
Message InputMsg = Message.CreateMessage(MessageVersion.Default,
"http://Microsoft.LobServices.SAP/2007/03/Idoc/SendIdoc",
stBW);
從配接器串流輸入 Flat-File IDOC
您會在輸入 ReceiveIdoc 作業中收到一般檔案IDOC。 配接器支援 ReceiveIdoc 作業要求訊息上的節點值串流。
若要在 WCF 通道模型中的 ReceiveIdoc 作業上支援節點值串流,您必須:
實作 System.Xml。XmlDictionaryWriter 能夠串流 IDOC 資料, (在 IDOC 資料) 上執行節點值串流。
使用這個XmlDictionaryWriter叫用其 WriteBodyContents方法來取用訊息。
實作 XmlDictionaryWriter
下列範例示範執行節點值串流的 XmlDictionaryWriter 實作。
using System;
using System.Xml;
using System.Text;
class FileXmlWriter : XmlDictionaryWriter
{
XmlTextWriter xts;
public FileXmlWriter(string file)
{
xts = new XmlTextWriter(file, Encoding.UTF8);
}
public override void WriteBase64(byte[] buffer, int index, int count)
{
xts.WriteBase64(buffer, index, count);
}
public override void WriteCData(string text)
{
xts.WriteCData(text);
}
public override void WriteCharEntity(char ch)
{
xts.WriteCharEntity(ch);
}
public override void WriteChars(char[] buffer, int index, int count)
{
xts.WriteChars(buffer, index, count);
}
public override void WriteComment(string text)
{
xts.WriteComment(text);
}
public override void WriteDocType(string name, string pubid, string sysid, string subset)
{
xts.WriteDocType(name, pubid, sysid, subset);
}
public override void WriteEndAttribute()
{
xts.WriteEndAttribute();
}
public override void WriteEndDocument()
{
xts.WriteEndDocument();
}
public override void WriteEndElement()
{
xts.WriteEndElement();
}
public override void WriteEntityRef(string name)
{
xts.WriteEntityRef(name);
}
public override void WriteFullEndElement()
{
xts.WriteFullEndElement();
}
public override void WriteProcessingInstruction(string name, string text)
{
xts.WriteProcessingInstruction(name, text);
}
public override void WriteRaw(string data)
{
xts.WriteRaw(data);
}
public override void WriteRaw(char[] buffer, int index, int count)
{
xts.WriteRaw(buffer, index, count);
}
public override void WriteStartAttribute(string prefix, string localName, string ns)
{
xts.WriteStartAttribute(prefix, localName, ns);
}
public override void WriteStartDocument(bool standalone)
{
xts.WriteStartDocument(standalone);
}
public override void WriteStartDocument()
{
xts.WriteStartDocument();
}
public override void WriteStartElement(string prefix, string localName, string ns)
{
xts.WriteStartElement(localName);
}
public override void WriteString(string text)
{
xts.WriteString(text);
}
public override void WriteSurrogateCharEntity(char lowChar, char highChar)
{
xts.WriteSurrogateCharEntity(lowChar, highChar);
}
public override void WriteWhitespace(string ws)
{
xts.WriteWhitespace(ws);
}
public override void Close()
{
xts.Close();
}
public override void Flush()
{
xts.Flush();
}
public override string LookupPrefix(string ns)
{
return xts.LookupPrefix(ns);
}
public override WriteState WriteState
{
get { return xts.WriteState; }
}
}
使用 XmlDictionaryWriter 取用訊息
下列範例示範如何使用上述範例中實作的 FileXmlWriter 來取用 ReceiveIdoc 要求訊息。 (FileWriter 類別是由子類別 XmlDictionaryWriter.) 建立。此範例會使用 IReplyChannel 通道來接收 ReceiveIdoc 作業。 已省略通道建立的詳細資料。 ReceiveIdoc 要求訊息會寫入檔案。
// Receive the ReceiveIdoc request message from the adapter.
RequestContext rc = channel.ReceiveRequest();
Message inputMsg = rc.RequestMessage;
// Stream the request message to received_idoc.xml using the custom XmlDictionaryWriter.
FileXmlWriter fileXmlWriter = new FileXmlWriter("received_idoc.xml");
inputMsg.WriteBodyContents(fileXmlWriter);
fileXmlWriter.Flush();
fileXmlWriter.Close();