Streaming de tipos de datos lob de base de datos de Oracle mediante el modelo de canal WCF
El adaptador de Microsoft BizTalk para oracle Database admite el streaming de datos loB de un extremo a otro para determinadas operaciones. En las secciones de este tema se describe cómo implementar el streaming para los datos lob cuando se usa el modelo de canal WCF.
Para obtener información general sobre cómo el adaptador admite el streaming de tipos de datos LOB, consulte Streaming de tipos de datos de objetos grandes en el adaptador de Oracle Database. Debe leer este tema antes de continuar.
Hay disponible un ejemplo que muestra el streaming de datos loB en los ejemplos del SDK incluidos con el adaptador de oracle Database. Para obtener más información, consulte Ejemplos en el SDK.
Streaming de mensajes salientes al adaptador
El adaptador admite el streaming de datos loB de un extremo a otro para el mensaje de solicitud para la operación UpdateLOB.
Para admitir el streaming de un extremo a otro en operaciones UpdateLOB en el modelo de canal WCF, debe hacer lo siguiente:
Establezca la propiedad de enlace UseAmbientTransaction en true.
Implemente una clase System.ServiceModel.Channels.BodyWriter que sea capaz de transmitir los datos loB (realizando streaming de valor de nodo en los datos loB).
Realice la operación UpdateLOB dentro de un ámbito de transacción.
Cree el objeto System.ServiceModel.Message que se usa para invocar la operación proporcionando el cuerpo del mensaje con bodyWriter mediante una sobrecarga adecuada del método Message.Create .
Establecer la propiedad UseAmbientTransaction Binding
En el ejemplo siguiente se muestra cómo crear un enlace para el adaptador de base de datos de Oracle y establecer la propiedad de enlace UseAmbientTransaction .
// Create binding
OracleDBBinding odbBinding = new OracleDBBinding();
//set the binding property
binding.UseAmbientTransaction = true;
Implementación de bodyWriter
En el ejemplo siguiente se muestra una implementación de bodyWriter que realiza el streaming de valores de nodo.
/// <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
}
Realizar las operaciones dentro de un ámbito de transacción
En el ejemplo siguiente se muestra cómo realizar operaciones dentro de un ámbito de transacción.
// Create a transaction scope
using(TransactionScope tx = new TransactionScope())
{
// perform operations within the transaction
// ...
// ...
//Complete the transaction
tx.Complete()
}
Creación de un mensaje mediante BodyWriter
En el ejemplo siguiente se muestra cómo crear un mensaje de solicitud UpdateLOB mediante BodyWriter en el ejemplo anterior. Los datos del mensaje se leen de un archivo.
// 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();
}
Streaming de mensajes entrantes desde el adaptador
El adaptador admite el streaming de datos loB de un extremo a otro para los siguientes mensajes entrantes:
Mensaje de respuesta para funciones con parámetros OUT o IN OUT que contienen datos LOB. Tenga en cuenta que los parámetros RECORD TYPE pueden contener columnas de datos LOB.
Mensaje de respuesta para funciones con parámetros OUT REF CURSOR (o valores devueltos) que contienen datos LOB. Esto incluye el lado de salida de los parámetros IN OUT REF CURSOR.
Mensaje de respuesta para procedimientos con parámetros IN o IN OUT que contienen datos LOB. Tenga en cuenta que los parámetros RECORD TYPE pueden contener columnas de datos LOB.
Mensaje de respuesta para procedimientos con parámetros OUT REF CURSOR que contienen datos LOB. Esto incluye el lado de salida de los parámetros IN OUT REF CURSOR.
Mensaje de respuesta para las operaciones SQLEXECUTE que devuelven conjuntos de resultados que contienen datos LOB.
Mensaje de respuesta para tabla o vista Seleccionar operaciones que devuelven datos loB en el conjunto de resultados.
Mensaje de solicitud para la operación POLLINGSTMT (entrante)
Para admitir el streaming de un extremo a otro en un mensaje entrante en el modelo de canal WCF, debe hacer lo siguiente:
Implemente un System.Xml. XmlDictionaryWriter que es capaz de transmitir los datos LOB (realizando streaming de valor de nodo en los datos lob).
Use el mensaje invocando el método WriteBodyContents con este XmlDictionaryWriter.
Implementación de xmlDictionaryWriter
En el ejemplo siguiente se muestra una implementación de xmlDictionaryWriter que realiza el streaming de valores de nodo.
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; }
}
}
Consumo de un mensaje mediante xmlDictionaryWriter
En el ejemplo siguiente se muestra cómo consumir una tabla Select response message using the FileXmlWriter implementó en el ejemplo anterior. (La clase FileWriter se creó mediante la subclase XmlDictionaryWriter). En el ejemplo se usa un canal IRequestChannel para invocar la operación Select. Se han omitido los detalles de la creación del canal. El mensaje Seleccionar solicitud se lee de un archivo y el mensaje Seleccionar respuesta se escribe en un archivo.
// 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();
El siguiente XML muestra el mensaje de solicitud (contenido del archivo select.xml) para la operación Select. La tabla CUSTOMER contiene una columna BLOB denominada PHOTO.
<Select xmlns="http://Microsoft.LobServices.OracleDB/2007/03/SCOTT/Table/CUSTOMER">
<COLUMN_NAMES>*</COLUMN_NAMES>
<FILTER>NAME='Kim Ralls'</FILTER>
</Select>
Consulte también
Desarrollo de aplicaciones de Oracle Database mediante el modelo de canal WCF