Compartir a través de


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:

  1. Establezca la propiedad de enlace UseAmbientTransaction en true.

  2. 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).

  3. Realice la operación UpdateLOB dentro de un ámbito de transacción.

  4. 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:

  1. Implemente un System.Xml. XmlDictionaryWriter que es capaz de transmitir los datos LOB (realizando streaming de valor de nodo en los datos lob).

  2. 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