WCF チャネル モデルを使用して SAP で Flat-File IDOC をストリーミングする
Microsoft BizTalk Adapter for mySAP Business Suite では、SendIdoc 操作と ReceiveIdoc 操作のノード値ストリーミングがサポートされています。 これらの操作は、アダプターとの間でフラット ファイル (文字列) IDOC を送受信するために使用されます。 どちらの操作でも、IDOC 全体のデータは、1 つのノード (<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 操作でノード値ストリーミングをサポートするには、次の操作を行う必要があります。
System.Xml を実装 します。 IDOC データをストリーミングできる XmlDictionaryWriter (IDOC データでノード値ストリーミングを実行します)。
この XmlDictionaryWriter を使用して WriteBodyContents メソッドを呼び出して、Message を使用します。
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();