Freigeben über


Streaming von Oracle Database LOB-Datentypen mithilfe des WCF-Kanalmodells

Der Microsoft BizTalk-Adapter für Oracle-Datenbank unterstützt das End-to-End-Streaming von LOB-Daten für bestimmte Vorgänge. In den Abschnitten in diesem Thema wird beschrieben, wie Das Streaming für LOB-Daten implementiert wird, wenn Sie das WCF-Kanalmodell verwenden.

Hintergrundinformationen dazu, wie der Adapter das Streaming von LOB-Datentypen unterstützt, finden Sie unter Streaming großer Objektdatentypen im Oracle Database-Adapter. Sie sollten dieses Thema lesen, bevor Sie fortfahren.

Ein Beispiel, das das Datenstreaming von LOB veranschaulicht, ist in den SDK-Beispielen verfügbar, die mit dem Oracle Database-Adapter enthalten sind. Weitere Informationen finden Sie unter Beispiele im SDK.

Streaming ausgehender Nachrichten an den Adapter

Der Adapter unterstützt End-to-End-LOB-Datenstreaming für die Anforderungsmeldung für den UpdateLOB-Vorgang.

Um End-to-End-Streaming bei UpdateLOB-Vorgängen im WCF-Kanalmodell zu unterstützen, müssen Sie:

  1. Legen Sie die UseAmbientTransaction-Bindungseigenschaft auf true fest.

  2. Implementieren Sie einen System.ServiceModel.Channels.BodyWriter , der in der Lage ist, die LOB-Daten zu streamen (Knotenwert-Streaming für die LOB-Daten).

  3. Führen Sie den UpdateLOB-Vorgang innerhalb eines Transaktionsbereichs aus.

  4. Erstellen Sie system.ServiceModel.Message , die zum Aufrufen des Vorgangs verwendet wird, indem Sie den Nachrichtentext mit diesem BodyWriter mithilfe einer entsprechenden Überladung der Message.Create-Methode bereitstellen.

Festlegen der UseAmbientTransaction-Bindungseigenschaft

Das folgende Beispiel zeigt, wie Sie eine Bindung für den Oracle Database-Adapter erstellen und die UseAmbientTransaction-Bindungseigenschaft festlegen.

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

Implementieren eines BodyWriter

Das folgende Beispiel zeigt eine Implementierung eines BodyWriter-Steuerelements , das Das Streaming mit Knotenwert ausführt.

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

Ausführen der Vorgänge innerhalb eines Transaktionsbereichs

Das folgende Beispiel zeigt, wie Vorgänge innerhalb eines Transaktionsbereichs ausgeführt werden.

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

Erstellen einer Nachricht mit einem BodyWriter

Das folgende Beispiel zeigt, wie Sie eine UpdateLOB-Anforderungsnachricht mithilfe von BodyWriter im vorherigen Beispiel erstellen. Die Nachrichtendaten werden aus einer Datei gelesen.

// 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 eingehender Nachrichten vom Adapter

Der Adapter unterstützt End-to-End-LOB-Datenstreaming für die folgenden eingehenden Nachrichten:

  • Antwortmeldung für Funktionen mit OUT- oder IN OUT-Parametern, die LOB-Daten enthalten. Beachten Sie, dass RECORD TYPE-Parameter LOB-Datenspalten enthalten können.

  • Antwortmeldung für Funktionen mit OUT REF CURSOR-Parametern (oder Rückgabewerten), die LOB-Daten enthalten. Dies schließt die Ausgabeseite von IN OUT REF CURSOR-Parametern ein.

  • Antwortmeldung für Prozeduren mit IN- oder IN OUT-Parametern, die LOB-Daten enthalten. Beachten Sie, dass RECORD TYPE-Parameter LOB-Datenspalten enthalten können.

  • Antwortmeldung für Prozeduren mit OUT REF CURSOR-Parametern, die LOB-Daten enthalten. Dies schließt die Ausgabeseite von IN OUT REF CURSOR-Parametern ein.

  • Antwortmeldung für SQLEXECUTE-Vorgänge, die Resultsets zurückgeben, die LOB-Daten enthalten.

  • Antwortmeldung für Tabelle oder Ansicht Auswählen von Vorgängen, die LOB-Daten im Resultset zurückgeben.

  • Anforderungsnachricht für den (eingehenden) POLLINGSTMT-Vorgang

    Um End-to-End-Streaming für eine eingehende Nachricht im WCF-Kanalmodell zu unterstützen, müssen Sie:

  1. Implementieren sie eine System.Xml. XmlDictionaryWriter , der in der Lage ist, die LOB-Daten zu streamen (knotenwertbasiertes Streaming für die LOB-Daten).

  2. Nutzen Sie die Message , indem Sie die WriteBodyContents-Methode mit diesem XmlDictionaryWriter aufrufen.

Implementieren eines XmlDictionaryWriter

Das folgende Beispiel zeigt eine Implementierung eines XmlDictionaryWriter,das Knotenwertstreaming ausführt.

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

Verwenden einer Nachricht mit einem XmlDictionaryWriter

Das folgende Beispiel zeigt, wie eine Tabelle Select-Antwortnachricht mithilfe des im vorherigen Beispiel implementierten FileXmlWriter verwendet wird. (Die FileWriter-Klasse wurde durch Die Unterklassierung von XmlDictionaryWriter erstellt.) Im Beispiel wird ein IRequestChannel-Kanal verwendet, um den Select-Vorgang aufzurufen. Die Details der Kanalerstellung wurden nicht angegeben. Die Select-Anforderungsnachricht wird aus einer Datei gelesen, und die Select-Antwortnachricht wird in eine Datei geschrieben.

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

Der folgende XML-Code zeigt die Anforderungsmeldung (Inhalt der select.xml-Datei) für den Select-Vorgang an. Die TABELLE CUSTOMER enthält eine BLOB-Spalte mit dem Namen PHOTO.

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

Weitere Informationen

Entwickeln von Oracle Database-Anwendungen mithilfe des WCF-Kanalmodells