Condividi tramite


Streaming di tipi di dati LOB del database Oracle usando il modello di canale WCF

L'adapter Microsoft BizTalk per Oracle Database supporta lo streaming end-to-end dei dati LOB per determinate operazioni. Le sezioni di questo argomento descrivono come implementare lo streaming per i dati LOB quando si usa il modello di canale WCF.

Per informazioni in background sul modo in cui l'adapter supporta lo streaming dei tipi di dati LOB, vedere Streaming di tipi di dati di oggetti di grandi dimensioni nell'adapter Oracle Database. È necessario leggere questo argomento prima di procedere.

Un esempio che illustra lo streaming di dati LOB è disponibile negli esempi dell'SDK inclusi nell'adapter Oracle Database. Per altre informazioni, vedere Esempi nell'SDK.

Streaming di messaggi in uscita nell'adapter

L'adapter supporta lo streaming di dati LOB end-to-end per il messaggio di richiesta per l'operazione UpdateLOB.

Per supportare lo streaming end-to-end nelle operazioni UpdateLOB nel modello di canale WCF, è necessario:

  1. Impostare la proprietà di associazione UseAmbientTransaction su true.

  2. Implementare un oggetto System.ServiceModel.Channels.BodyWriter in grado di trasmettere i dati LOB (eseguendo lo streaming dei valori del nodo nei dati LOB).

  3. Eseguire l'operazione UpdateLOB all'interno di un ambito di transazione.

  4. Creare system.ServiceModel.Message usato per richiamare l'operazione fornendo il corpo del messaggio con questo BodyWriter usando un overload appropriato del metodo Message.Create .

Impostazione della proprietà UseAmbientTransaction Binding

Nell'esempio seguente viene illustrato come creare un'associazione per l'adapter Oracle Database e impostare la proprietà di associazione UseAmbientTransaction .

// Create binding  
OracleDBBinding odbBinding = new OracleDBBinding();  
  
//set the binding property  
binding.UseAmbientTransaction = true;  
  

Implementazione di un BodyWriter

Nell'esempio seguente viene illustrata un'implementazione di BodyWriter che esegue lo streaming node-value.

/// <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  
}  

Eseguire le operazioni all'interno di un ambito di transazione

Nell'esempio seguente viene illustrato come eseguire operazioni all'interno di un ambito di transazione.

// Create a transaction scope  
using(TransactionScope tx = new TransactionScope())  
{  
  // perform operations within the transaction  
  // ...  
  // ...  
  
  //Complete the transaction  
  tx.Complete()  
}  
  

Creazione di un messaggio usando bodywriter

Nell'esempio seguente viene illustrato come creare un messaggio di richiesta UpdateLOB usando BodyWriter nell'esempio precedente. I dati del messaggio sono letti da un file.

// 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 di messaggi in ingresso dall'adapter

L'adapter supporta lo streaming di dati LOB end-to-end per i messaggi in ingresso seguenti:

  • Messaggio di risposta per le funzioni con parametri OUT o IN OUT che contengono dati LOB. Si noti che i parametri RECORD TYPE possono contenere colonne di dati LOB.

  • Messaggio di risposta per le funzioni con parametri OUT REF CURSOR (o valori restituiti) che contengono dati LOB. Include il lato output dei parametri IN OUT REF CURSOR.

  • Messaggio di risposta per le procedure con parametri IN o IN OUT che contengono dati LOB. Si noti che i parametri RECORD TYPE possono contenere colonne di dati LOB.

  • Messaggio di risposta per le procedure con parametri OUT REF CURSOR che contengono dati LOB. Include il lato output dei parametri IN OUT REF CURSOR

  • Messaggio di risposta per le operazioni SQLEXECUTE che restituiscono set di risultati contenenti dati LOB.

  • Messaggio di risposta per Le operazioni Table o view Select che restituiscono i dati LOB nel set di risultati.

  • Messaggio di richiesta per l'operazione POLLINGSTMT (in ingresso)

    Per supportare lo streaming end-to-end in un messaggio in ingresso nel modello di canale WCF, è necessario:

  1. Implementare un System.Xml. XmlDictionaryWriter in grado di trasmettere i dati LOB (esecuzione dello streaming dei valori del nodo nei dati LOB).

  2. Utilizzare il messaggio richiamando il metodo WriteBodyContents con questo oggetto XmlDictionaryWriter.

Implementazione di un oggetto XmlDictionaryWriter

Nell'esempio seguente viene illustrata un'implementazione di un oggetto XmlDictionaryWriter che esegue lo streaming node-value.

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; }  
    }  
  
}  

Utilizzo di un messaggio tramite xmlDictionaryWriter

Nell'esempio seguente viene illustrato come usare un messaggio di risposta Select tabella usando FileXmlWriter implementato nell'esempio precedente. La classe FileWriter è stata creata con sottoclasse XmlDictionaryWriter. Nell'esempio viene usato un canale IRequestChannel per richiamare l'operazione Select. I dettagli della creazione del canale sono stati omessi. Il messaggio Select request viene letto da un file e il messaggio Select response viene scritto in un file.

// 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();  

Il codice XML seguente mostra il messaggio di richiesta (contenuto del file di select.xml) per l'operazione Seleziona. La tabella CUSTOMER contiene una colonna BLOB denominata PHOTO.

<Select xmlns="http://Microsoft.LobServices.OracleDB/2007/03/SCOTT/Table/CUSTOMER">  
  <COLUMN_NAMES>*</COLUMN_NAMES>  
  <FILTER>NAME='Kim Ralls'</FILTER>  
</Select>  

Vedere anche

Sviluppare applicazioni di Database Oracle usando il modello di canale WCF