使用 WCF 通道模型流式处理 Oracle Database LOB 数据类型
适用于 Oracle 数据库的 Microsoft BizTalk 适配器支持对某些操作进行 LOB 数据的端到端流式处理。 本主题中的部分介绍了在使用 WCF 通道模型时如何实现 LOB 数据的流式处理。
有关适配器如何支持 LOB 数据类型流式处理的背景信息,请参阅 在 Oracle 数据库适配器中流式处理大型对象数据类型。 在继续之前,应先阅读本主题。
Oracle 数据库适配器随附的 SDK 示例中提供了一个演示 LOB 数据流的示例。 有关详细信息,请参阅 SDK 中的示例。
将出站消息流式传输到适配器
适配器支持对 UpdateLOB 操作的请求消息进行端到端 LOB 数据流式处理。
若要在 WCF 通道模型中支持对 UpdateLOB 操作进行端到端流式处理,必须:
将 UseAmbientTransaction 绑定属性设置为 true。
实现能够流式处理 LOB 数据的 System.ServiceModel.Channels.BodyWriter , (对 LOB 数据) 执行节点值流式处理。
在事务范围内执行 UpdateLOB 操作。
通过使用 Message.Create 方法的适当重载为此 BodyWriter 提供消息正文,创建用于调用操作的 System.ServiceModel.Message。
设置 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 的表 Select 响应消息。 (FileWriter 类是由 XmlDictionaryWriter.) 该示例使用 IRequestChannel 通道调用 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>