使用 WCF 通道模型串流 Oracle Database LOB 資料類型
Microsoft BizTalk Adapter for Oracle Database 支援特定作業的 LOB 資料的端對端串流。 本主題中的各節說明如何使用 WCF 通道模型來實作 LOB 資料的串流。
如需配接器如何支援 LOB 資料類型串流的背景資訊,請參閱 在 Oracle 資料庫配接器中串流大型物件資料類型。 您應該先閱讀本主題,再繼續進行。
示範 LOB 資料流的範例可在 Oracle 資料庫配接器隨附的 SDK 範例中使用。 如需詳細資訊,請參閱 SDK 中的範例。
將輸出訊息串流至配接器
配接器支援 UpdateLOB 作業要求訊息的端對端 LOB 資料串流。
若要支援 WCF 通道模型中 UpdateLOB 作業的端對端串流,您必須:
將 UseAmbientTransaction 系結屬性設定為 true。
實作 System.ServiceModel.Channels.BodyWriter ,其能夠串流 LOB 資料, (在 LOB 資料) 上執行節點值串流。
在交易範圍內執行 UpdateLOB 作業。
使用Message.Create方法的適當多載,建立用來叫用作業的System.ServiceModel.Message,方法是使用這個BodyWriter提供訊息本文。
設定 UseAmbientTransaction 系結屬性
下列範例示範如何建立 Oracle 資料庫配接器的系結,並設定 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 資料行。
具有 OUT REF CURSOR 參數之函式的回應訊息 (或傳回包含 LOB 資料的) 值。 這包括 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。XmlDictionaryWriter ,能夠串流 LOB 資料 (在 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 來取用資料表 選取回應訊息。 (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.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>