Freigeben über


Empfangen von abfragenbasierten datenveränderten Nachrichten in Oracle-Datenbank mithilfe des WCF-Kanalmodells

Sie können den Microsoft BizTalk-Adapter für Oracle-Datenbank konfigurieren, um eine Oracle-Datenbanktabelle oder -Ansicht nach Datenänderungen abzufragen. Um einen solchen Abrufvorgang auszuführen, führt der Adapter regelmäßig eine SQL-Abfrage für eine Oracle-Tabelle oder -Sicht aus, gefolgt von einem optionalen PL/SQL-Codeblock. Die Ergebnisse der SQL-Abfrage werden dann vom Oracle Database-Adapter als stark typisiertes Resultset in einem eingehenden POLLINGSTMT-Vorgang an Ihren Code zurückgegeben. Weitere Informationen zum Mechanismus zum Konfigurieren und Durchführen von Abfragen in einer Oracle-Datenbank mithilfe des Oracle Database-Adapters finden Sie unter Empfangen von abrufbasierten datenveränderten Nachrichten im Oracle Database-Adapter. Es wird dringend empfohlen, dieses Thema zu lesen, bevor Sie fortfahren.

Sie konfigurieren den Oracle Database-Adapter zum Abfragen der Oracle-Datenbanktabelle oder -ansicht, indem Sie Bindungseigenschaften für eine instance von OracleDBBinding festlegen. Im WCF-Kanalmodell verwenden Sie diese Bindung dann, um einen Kanallistener zu erstellen, aus dem Sie einen IInputChannel-Kanal abrufen können, um den POLLINGSTMT-Vorgang vom Adapter zu empfangen.

Eine Übersicht über das Empfangen von Vorgängen mit einem IInputChannel in WCF finden Sie unter Service Channel-Level Programming.

Die Abschnitte in diesem Thema enthalten Informationen zur Durchführung von Abfragen für Oracle-Datenbanktabellen und -ansichten mithilfe des WCF-Kanalmodells.

Verwenden der POLLINGSTMT-Anforderungsnachricht

Der Adapter ruft den POLLINGSTMT-Vorgang für Ihren Code auf, um die Oracle-Datenbank abzufragen. Das heißt, der Adapter sendet eine POLLINGSTMT-Anforderungsnachricht, die Sie über ein IInputChannel-Kanal-Shape erhalten. Die POLLINGSTMT-Anforderungsnachricht enthält das Resultset der Abfrage, die von der PollingStatement-Bindungseigenschaft angegeben wird. Sie können die POLLINGSTMT-Nachricht auf zwei Arten nutzen:

  • Um die Nachricht mithilfe von Node-Wert-Streaming zu nutzen, müssen Sie die WriteBodyContents-Methode für die Antwortnachricht aufrufen und ihr einen XmlDictionaryWriter übergeben, der das Knotenwertstreaming implementiert.

  • Um die Nachricht mithilfe des Knotenstreamings zu nutzen, können Sie GetReaderAtBodyContents in der Antwortnachricht aufrufen, um einen XmlReader abzurufen.

    Sie verwenden in der Regel Knotenwert-Streaming, um Resultsets zu nutzen, die Oracle LOB-Datenspalten enthalten.

    Weitere Informationen zur Nachrichtenstruktur des POLLINGSTMT-Vorgangs finden Sie unter Nachrichtenschemas für die Abrufvorgänge.

    Weitere Informationen dazu, wie der Oracle Database-Adapter das Streaming für BRANCHENdaten unterstützt, finden Sie unter Streaming von Datentypen für große Objekte im Oracle Database-Adapter.

    Weitere Informationen zum Implementieren des Knoten-Wert-Streamings in Ihrem Code zur Unterstützung des End-to-End-Streamings von LOB-Daten finden Sie unter Streaming von Oracle Database LOB-Datentypen mithilfe des WCF-Kanalmodells.

Informationen zu den in diesem Thema verwendeten Beispielen

Im Beispiel in diesem Thema wird scott verwendet. ACCOUNTACTIVITY-Tabelle und die SCOTT-Tabelle. ACCOUNT_PKG. PROCESS_ACTIVITY-Funktion. Mit den Beispielen wird ein Skript zum Generieren dieser Artefakte bereitgestellt. Das Beispiel führt die folgenden Vorgänge aus:

  • Als Teil der Abfrage-Anweisung werden alle Datensätze aus der Tabelle ACCOUNTACTIVITY ausgewählt und in der Konsole angezeigt.

  • Als Teil der Post-Poll-Anweisung ruft das Beispiel die PROCESS_ACTIVITY-Funktion auf, die alle Datensätze aus der TABELLE ACCOUNTACTIVITY in die TABELLE ACTIVITYHISTORY verschiebt.

  • Nachfolgende Umfragen für die Tabelle ACCOUNTACTIVITY geben keine Datensätze zurück. Wenn das Beispiel jedoch im Rahmen des Abrufvorgangs weitere Datensätze zurückgeben soll, müssen Sie einige Datensätze in die Tabelle ACCOUNTACTIVITY einfügen. Dazu führen Sie das mit den Beispielen bereitgestellte Skript more_activity_data.sql aus.

    Weitere Informationen zu den Beispielen finden Sie unter Adapterbeispiele.

Wie kann ich eine Oracle-Datenbank mit einem IInputChannel abfragen?

Führen Sie die folgenden Schritte aus, um eine Oracle-Datenbanktabelle oder -Ansicht zum Empfangen von Datenänderungsnachrichten mithilfe des WCF-Kanalmodells abzufragen.

So empfangen Sie datenveränderte Nachrichten mithilfe eines IInputChannel

  1. Erstellen Sie ein Visual C#-Projekt in Visual Studio. Erstellen Sie für dieses Thema eine Konsolenanwendung.

  2. Fügen Sie im Projektmappen-Explorer Verweis auf Microsoft.Adapters.OracleDB, Microsoft.ServiceModel.Channels, System.ServiceModelund System.Runtime.Serializationhinzu.

  3. Öffnen Sie die Datei Program.cs, und fügen Sie die folgenden Namespaces hinzu:

    • Microsoft.Adapters.OracleDB

    • Microsoft.ServiceModel.Channels

    • System.ServiceModel

    • System.ServiceModel.Description

    • System.ServiceModel.Channels

    • System.Xml

    • System.Runtime.Serialization

    • System.IO

    • Microsoft.ServiceModel.Channels.Common

  4. Erstellen Sie eine instance von OracleDBBinding, und legen Sie die Bindungseigenschaften fest, die zum Konfigurieren der Abfrage erforderlich sind. Mindestens müssen Sie die Bindungseigenschaften InboundOperationType, PollingStatement und PollingInterval festlegen. In diesem Beispiel legen Sie auch die PostPollStatement-Bindungseigenschaft fest. Weitere Informationen zu Bindungseigenschaften, die zum Konfigurieren der Abfrage verwendet werden, finden Sie unter Empfangen von abrufbasierten datenveränderten Nachrichten im Oracle Database-Adapter.

    OracleDBBinding binding = new OracleDBBinding();  
    binding.InboundOperationType = InboundOperation.Polling;  
    binding.PollingInterval = 30;  
    binding.PollingStatement = "SELECT * FROM ACCOUNTACTIVITY FOR UPDATE";  
    binding.PostPollStatement = "BEGIN ACCOUNT_PKG.PROCESS_ACTIVITY(); END;"  
    
  5. Erstellen Sie eine Bindungsparameterauflistung, und legen Sie die Anmeldeinformationen fest.

    ClientCredentials credentials = new ClientCredentials();  
    credentials.UserName.UserName = "SCOTT";  
    credentials.UserName.Password = "TIGER";  
    
    BindingParameterCollection bindingParams = new BindingParameterCollection();  
    bindingParams.Add(credentials);  
    
  6. Erstellen Sie einen Kanallistener, und öffnen Sie ihn. Sie erstellen den Listener, indem Sie die BuildChannelListener<IInputChannel-Methode> für OracleDBBinding aufrufen. Sie können den Zielnamespace für den POLLINGSTMT-Vorgang ändern, indem Sie die PollingId-Eigenschaft im Verbindungs-URI festlegen. Weitere Informationen zum Adapterverbindungs-URI finden Sie unter Erstellen des Oracle Database-Verbindungs-URI.

    IChannelListener<IInputChannel> listener = binding.BuildChannelListener<IInputChannel>(connectionUri, bindingParams);  
    listener.Open();  
    
  7. Rufen Sie einen IInputChannel-Kanal ab, indem Sie die AcceptChannel-Methode im Listener aufrufen und öffnen.

    IInputChannel channel = listener.AcceptChannel();  
    channel.Open();  
    
  8. Rufen Sie Receive im Kanal auf, um die nächste POLLINGSTMT-Nachricht vom Adapter abzurufen.

    Message message = channel.Receive();  
    
  9. Verwenden Sie das vom POLLINGSTMT-Vorgang zurückgegebene Resultset. Sie können die Nachricht mit einem XmlReader oder einem XmlDictionaryWriter nutzen.

    XmlReader reader = message.GetReaderAtBodyContents();  
    
  10. Schließen Sie den Kanal, wenn Sie die Verarbeitung der Anforderung abgeschlossen haben.

    channel.Close()  
    

    Wichtig

    Sie müssen den Kanal schließen, nachdem Sie die Verarbeitung des POLLINGSTMT-Vorgangs abgeschlossen haben. Ein Fehler beim Schließen des Kanals kann sich auf das Verhalten Ihres Codes auswirken.

  11. Schließen Sie den Listener, wenn Sie mit dem Empfang von Daten geänderten Nachrichten fertig sind.

    listener.Close()  
    

    Wichtig

    Das Schließen des Listeners führt nicht zum Schließen von Kanälen, die mit dem Listener erstellt wurden. Sie müssen jeden mit dem Listener erstellten Kanal explizit schließen.

Beispiel

Das folgende Beispiel zeigt, wie Sie den Oracle Database-Adapter konfigurieren, um Oracle-Datenbanktabellen und -ansichten abzufragen und den POLLLINGSTMT-Vorgang mithilfe des WCF-Kanalmodells zu empfangen. Das im POLLINGSTMT-Vorgang zurückgegebene Resultset wird mithilfe eines XmlReader-Elements in die Konsole geschrieben.

using System;  
using System.Collections.Generic;  
using System.Text;  
  
// Add WCF, WCF LOB Adapter SDK, and Oracle Database adapter namepaces  
using System.ServiceModel;  
using System.ServiceModel.Description;  
using Microsoft.ServiceModel.Channels;  
using Microsoft.Adapters.OracleDB;  
  
// Add this namespace for channel model  
using System.ServiceModel.Channels;  
  
using System.Xml;  
using System.Runtime.Serialization;  
using System.IO;  
  
// Include this namespace for the WCF LOB Adapter SDK and Oracle exceptions  
using Microsoft.ServiceModel.Channels.Common;  
  
namespace OraclePollingCM  
{  
    class Program  
    {  
        static void Main(string[] args)  
        {  
            Uri connectionUri = new Uri("oracleDB://ADAPTER/");  
  
            IChannelListener<IInputChannel> listener = null;  
            IInputChannel channel = null;  
  
            // set timeout to receive POLLINGSTMT message  
            TimeSpan messageTimeout = new TimeSpan(0, 0, 30);  
  
            Console.WriteLine("Sample Started");  
  
            try  
            {  
                // Create a binding: specify the InboundOperationType, PollingInterval (in seconds), the           
                // PollingStatement,and the PostPollStatement.  
                OracleDBBinding binding = new OracleDBBinding();  
                binding.InboundOperationType = InboundOperation.Polling;  
                binding.PollingInterval = 30;  
                binding.PollingStatement = "SELECT * FROM ACCOUNTACTIVITY FOR UPDATE";  
                binding.PostPollStatement = "BEGIN ACCOUNT_PKG.PROCESS_ACTIVITY(); END;";  
  
                // Create a binding parameter collection and set the credentials  
                ClientCredentials credentials = new ClientCredentials();  
                credentials.UserName.UserName = "SCOTT";  
                credentials.UserName.Password = "TIGER";  
  
                BindingParameterCollection bindingParams = new BindingParameterCollection();  
                bindingParams.Add(credentials);  
  
                Console.WriteLine("Opening listener");  
                // get a listener  from the binding  
                listener = binding.BuildChannelListener<IInputChannel>(connectionUri, bindingParams);  
                listener.Open();  
  
                Console.WriteLine("Opening channel");  
                // get a channel from the listener  
                channel = listener.AcceptChannel();  
                channel.Open();  
  
                Console.WriteLine("Channel opened -- waiting for polled data");  
                Console.WriteLine("Receive request timeout is {0}", messageTimeout);  
  
                // Poll five times with the specified message timeout   
                // If a timeout occurs polling will be aborted  
                for (int i = 0; i < 5; i++)  
                {  
                    Console.WriteLine("Polling: " + i);  
                    Message message = null;  
                    XmlReader reader = null;  
                    try  
                    {  
                        //Message is received so process the results  
                        message = channel.Receive(messageTimeout);  
                    }  
                    catch (System.TimeoutException toEx)  
                    {  
                        Console.WriteLine("\nNo data for request number {0}: {1}", i + 1, toEx.Message);  
                        continue;  
                    }  
  
                    // Get the query results using an XML reader  
                    try  
                    {  
                        reader = message.GetReaderAtBodyContents();  
                    }  
                    catch (Exception ex)  
                    {  
                        Console.WriteLine("Exception :" + ex);  
                        throw;  
                    }  
  
                    // Write the TID, ACCOUNT, AMOUNT, and TRANSDATE for each record to the Console  
                    Console.WriteLine("\nPolling data received for request number {0}", i+1);  
                    Console.WriteLine("Tx ID\tACCOUNT\tAMOUNT\tTx DATE");  
  
                    while (reader.Read())  
                    {  
                        if (reader.IsStartElement())  
                        {  
                            switch (reader.Name)  
                            {  
                                case "POLLINGSTMTRECORD":  
                                    Console.Write("\n");  
                                    break;  
  
                                case "TID":  
                                    reader.Read();  
                                    Console.Write(reader.ReadString() + "\t");  
                                    break;  
  
                                case "ACCOUNT":  
                                    reader.Read();  
                                    Console.Write(reader.ReadString() + "\t");  
                                    break;  
                                case "AMOUNT":  
                                    reader.Read();  
                                    Console.Write(reader.ReadString() + "\t");  
                                    break;  
  
                                case "TRANSDATE":  
                                    reader.Read();  
                                    Console.Write(reader.ReadString() + "\t");  
                                    break;  
  
                                default:  
                                    break;  
                            }  
                        }  
                    }  
  
                    // return the cursor  
                    Console.WriteLine();  
  
                    // close the reader  
                    reader.Close();  
  
                    //            To save the polling data to a file you can REPLACE the code above with the following  
                    //  
                    //            XmlDocument doc = new XmlDocument();  
                    //            doc.Load(reader);  
                    //            using (XmlWriter writer = XmlWriter.Create("PollingOutput.xml"))  
                    //            {  
                    //                doc.WriteTo(writer);  
                    //            }  
                    message.Close();  
                }  
  
                Console.WriteLine("\nPolling done -- hit <RETURN> to finish");  
                Console.ReadLine();  
            }  
            catch (TargetSystemException tex)  
            {  
                Console.WriteLine("Exception occurred on the Oracle Database");  
                Console.WriteLine(tex.InnerException.Message);  
            }  
            catch (ConnectionException cex)  
            {  
                Console.WriteLine("Exception occurred connecting to the Oracle Database");  
                Console.WriteLine(cex.InnerException.Message);  
            }  
            catch (Exception ex)  
            {  
                Console.WriteLine("Exception is: " + ex.Message);  
                if (ex.InnerException != null)  
                {  
                    Console.WriteLine("Inner Exception is: " + ex.InnerException.Message);  
                }  
            }  
            finally  
            {  
                // IMPORTANT: close the channel and listener to stop polling  
                if (channel != null)  
                {  
                    if (channel.State == CommunicationState.Opened)  
                        channel.Close();  
                    else  
                        channel.Abort();  
                }  
  
                if (listener != null)  
                {  
                    if (listener.State == CommunicationState.Opened)  
                        listener.Close();  
                    else  
                        listener.Abort();  
                }  
            }  
        }  
    }  
}  

Weitere Informationen

Entwickeln von Oracle Database-Anwendungen mithilfe des WCF-Kanalmodells