WCF チャネル モデルを使用した Oracle データベース LOB データ型のストリーミング
Microsoft BizTalk Adapter for Oracle Database では、特定の操作に対する LOB データのエンド ツー エンド ストリーミングがサポートされています。 このトピックのセクションでは、WCF チャネル モデルを使用するときに LOB データのストリーミングを実装する方法について説明します。
アダプターが LOB データ型のストリーミングをサポートする方法の背景情報については、「 Oracle Database アダプターでのラージ オブジェクト データ型のストリーミング」を参照してください。 先に進む前に、このトピックをお読みください。
LOB データ ストリーミングを示すサンプルは、Oracle Database アダプターに含まれている SDK サンプルで入手できます。 詳細については、「 SDK のサンプル」を参照してください。
アダプターへの送信メッセージのストリーミング
アダプターは、UpdateLOB 操作の要求メッセージに対してエンド ツー エンドの LOB データ ストリーミングをサポートします。
WCF チャネル モデルの UpdateLOB 操作でエンド ツー エンド ストリーミングをサポートするには、次の操作を行う必要があります。
UseAmbientTransaction バインド プロパティを true に設定します。
LOB データをストリーミングできる System.ServiceModel.Channels.BodyWriter を実装します (LOB データに対してノード値ストリーミングを実行します)。
トランザクション スコープ内で UpdateLOB 操作を実行します。
Message.Create メソッドの適切なオーバーロードを使用して、この BodyWriter でメッセージ本文を指定して、操作の呼び出しに使用する System.ServiceModel.Message を作成します。
UseAmbientTransaction バインディング プロパティの設定
次の例では、Oracle Database アダプターのバインドを作成し、 UseAmbientTransaction バインド プロパティを設定する方法を示します。
// Create binding
OracleDBBinding odbBinding = new OracleDBBinding();
//set the binding property
binding.UseAmbientTransaction = true;
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
}
トランザクション スコープ内で操作を実行する
次の例は、トランザクション スコープ内で操作を実行する方法を示しています。
// Create a transaction scope
using(TransactionScope tx = new TransactionScope())
{
// perform operations within the transaction
// ...
// ...
//Complete the transaction
tx.Complete()
}
BodyWriter を使用したメッセージの作成
次の例は、前の例の BodyWriter を使用して UpdateLOB 要求メッセージを作成する方法を示しています。 メッセージ データはファイルから読み取られます。
// Create a transaction scope
using(TransactionScope tx = new TransactionScope())
{
XmlReader readerIn = XmlReader.Create ("updatelob.xml");
// StreamingBodyWrtier class is responsible for streaming
StreamingBodyWriter stBW = new StreamingBodyWriter(readerIn, chunkSize);
Message InputMsg = Message.CreateMessage(MessageVersion.Default,
"http://Microsoft.LobServices.OracleDB/2007/03/SCOTT/Table/CUSTOMER/UpdateLOB",
stBW);
//Send the request message and get the output message
OutputMsg = channel.Request(InputMsg);
tx.Complete();
}
アダプターからの受信メッセージのストリーミング
アダプターは、次の受信メッセージのエンド ツー エンド LOB データ ストリーミングをサポートしています。
LOB データを含む OUT パラメーターまたは IN OUT パラメーターを持つ関数の応答メッセージ。 RECORD TYPE パラメーターには LOB データ列を含めることができます。
LOB データを含む OUT REF CURSOR パラメーター (または戻り値) を持つ関数の応答メッセージ。 これには、IN OUT REF CURSOR パラメーターの出力側が含まれます。
LOB データを含む IN パラメーターまたは IN OUT パラメーターを持つプロシージャの応答メッセージ。 RECORD TYPE パラメーターには LOB データ列を含めることができます。
LOB データを含む OUT REF CURSOR パラメーターを持つプロシージャーの応答メッセージ。 これには、IN OUT REF CURSOR パラメーターの出力側が含まれます
LOB データを含む結果セットを返す SQLEXECUTE 操作の応答メッセージ。
テーブルまたはビューの応答メッセージ 結果セット内の LOB データを返す操作を選択します。
(受信) POLLINGSTMT 操作の要求メッセージ
WCF チャネル モデルの受信メッセージでエンド ツー エンド ストリーミングをサポートするには、次の手順を実行する必要があります。
System.Xml を実装 します。LOB データをストリーミングできる XmlDictionaryWriter (LOB データに対するノード値ストリーミングの実行)。
この 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 を使用して、テーブル Select 応答メッセージを使用する方法を示します。 ( FileWriter クラスは、 XmlDictionaryWriter をサブクラス化することによって作成されました)。この例では、 IRequestChannel チャネルを使用して Select 操作を呼び出します。 チャネル作成の詳細は省略されています。 Select 要求メッセージはファイルから読み取られ、Select 応答メッセージはファイルに書き込まれます。
// Read Select message body from a file
XmlReader readerIn = XmlReader.Create("select.xml");
Message InputMsg = Message.CreateMessage(MessageVersion.Default,
"http://Microsoft.LobServices.OracleDB/2007/03/SCOTT/Table/CUSTOMER/Select", readerIn);
Message OutputMsg = channel.Request(InputMsg);
// Streaming response message to select_output.xml using the custom XmlDictionaryWriter;
FileXmlWriter fileXmlWriter = new FileXmlWriter("select_output.xml");
OutputMsg.WriteBodyContents(fileXmlWriter);
fileXmlWriter.Flush();
fileXmlWriter.Close();
// Streaming complete close output message;
OutputMsg.Close();
次の XML は、Select 操作の要求メッセージ (select.xml ファイルの内容) を示しています。 CUSTOMER テーブルには、PHOTO という名前の BLOB 列が含まれています。
<Select xmlns="http://Microsoft.LobServices.OracleDB/2007/03/SCOTT/Table/CUSTOMER">
<COLUMN_NAMES>*</COLUMN_NAMES>
<FILTER>NAME='Kim Ralls'</FILTER>
</Select>