WCF 채널 모델을 사용하여 SAP에서 Flat-File IDOC 스트리밍
MySAP Business Suite용 Microsoft BizTalk 어댑터는 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 작업에서 노드 값 스트리밍을 지원하려면 다음을 수행해야 합니다.
System.Xml 구현 합니다. IDOC 데이터를 스트리밍할 수 있는 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();