Microsoft BizTalk Adapter for mySAP Business Suite では、SendIdoc 操作と ReceiveIdoc 操作のノード値ストリーミングがサポートされています。 これらの操作は、アダプターとの間でフラット ファイル (文字列) IDOC を送受信するために使用されます。 どちらの操作でも、IDOC 全体のデータは、単一ノード (<idocData>) の下の文字列に含まれます。 大規模な IDOC の場合、アダプターとコードの間で IDOC データをストリーミングすると、大量のメモリ リソースが節約される可能性があります。
アダプターがストリーミングをサポートする方法の背景情報については、「 ストリーミングと SAP アダプター」を参照してください。 先に進む前に、このトピックをお読みください。
このトピックのセクションでは、WCF チャネル モデルを使用するときに SendIdoc および ReceiveIdoc 操作のノード値ストリーミングを実装する方法について説明します。
アダプターへのアウトバウンド Flat-File IDOC のストリーミング
アダプターは、SendIdoc 操作の要求メッセージでノード値ストリーミングをサポートします。
WCF チャネル モデルの SendIdoc 操作でノード値ストリーミングをサポートするには、次の操作を行う必要があります。
IDOC データをストリーミングできる System.ServiceModel.Channels.BodyWriter を実装します (IDOC データに対してノード値ストリーミングを実行します)。
Message.Create メソッドの適切なオーバーロードを使用して、この BodyWriter でメッセージ本文を指定して、操作の呼び出しに使用する 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 操作でノード値ストリーミングをサポートするには、次の操作を行う必要があります。
IDOC データをストリーミングできる System.Xml.Xml.XmlDictionaryWriter を実装します (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();