Condividi tramite


Ricevere messaggi di modifica dei dati basati sul polling nel database Oracle usando il modello di canale WCF

È possibile configurare l'adapter Microsoft BizTalk per Oracle Database per interrogare una tabella o una vista del database Oracle riguardo eventuali modifiche ai dati. Per eseguire un'operazione di polling di questo tipo, l'adapter esegue periodicamente una query SQL su una tabella o una vista Oracle seguita da un blocco di codice PL/SQL facoltativo. I risultati della query SQL vengono quindi restituiti dall'adattatore Oracle Database al tuo codice come un set di risultati fortemente tipizzati in un'operazione di POLLINGSTMT in ingresso. Per altre informazioni sul meccanismo usato per configurare ed eseguire il polling in un database Oracle tramite l'adapter Oracle Database, vedere Ricevere messaggi di modifica dei dati basati sul polling nell'adapter Oracle Database. Prima di procedere, è consigliabile leggere questo argomento.

È possibile configurare l'adapter Oracle Database per eseguire il polling di una tabella o vista del database Oracle impostando le proprietà di associazione in un'istanza di OracleDBBinding. Nel modello di canale WCF si usa quindi questa associazione per creare un listener di canale da cui è possibile ottenere un canale IInputChannel per ricevere l'operazione POLLINGSTMT dall'adapter.

Per una panoramica di come ricevere operazioni tramite un IInputChannel in WCF, vedere Programmazione di servizi Channel-Level.

Le sezioni di questo argomento forniscono informazioni utili per effettuare il polling delle tabelle e viste del database Oracle usando il modello di canale WCF.

Utilizzo del messaggio di richiesta POLLINGSTMT

L'adapter richiama l'operazione POLLINGSTMT sul tuo codice per eseguire il polling del database Oracle. Ovvero, l'adapter invia un messaggio di richiesta POLLINGSTMT che viene ricevuto tramite un tipo di canale IInputChannel. Il messaggio di richiesta POLLINGSTMT contiene il set di risultati della query specificata dalla proprietà di associazione PollingStatement . È possibile utilizzare il messaggio POLLINGSTMT in uno dei due modi seguenti:

Informazioni sugli esempi usati in questo argomento

L'esempio in questo argomento usa la tabella SCOTT.ACCOUNTACTIVITY e la funzione SCOTT.ACCOUNT_PKG.PROCESS_ACTIVITY. Uno script per generare questi artefatti viene fornito con gli esempi. Nell'esempio vengono eseguite le operazioni seguenti:

  • Come parte dell'istruzione di polling, seleziona tutti i record dalla tabella ACCOUNTACTIVITY e li visualizza sulla console.

  • Come parte dell'istruzione post poll, nell'esempio viene richiamata la funzione PROCESS_ACTIVITY che sposta tutti i record dalla tabella ACCOUNTACTIVITY alla tabella ACTIVITYHISTORY.

  • I sondaggi successivi nella tabella ACCOUNTACTIVITY non restituiscono record. Tuttavia, se si desidera che l'esempio restituisca più record come parte dell'operazione di polling, è necessario inserire alcuni record nella tabella ACCOUNTACTIVITY. A tale scopo, eseguire lo script di more_activity_data.sql fornito con gli esempi.

    Per ulteriori informazioni sugli esempi, vedere Adapter Samples.

Come si esegue il polling di un database Oracle usando un IInputChannel?

Per eseguire il polling di una tabella o di una vista di database Oracle per ricevere messaggi di modifica dei dati usando il modello di canale WCF, seguire questa procedura.

Per ricevere messaggi su cambiamenti dei dati tramite un IInputChannel

  1. Creare un progetto Visual C# in Visual Studio. Per questo argomento, creare un'applicazione console.

  2. In Esplora soluzioni aggiungere il riferimento a Microsoft.Adapters.OracleDB, Microsoft.ServiceModel.Channels, System.ServiceModele System.Runtime.Serialization.

  3. Aprire il file Program.cs e aggiungere i seguenti namespace:

    • 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. Creare un'istanza di OracleDBBinding e impostare le proprietà di associazione necessarie per configurare il polling. È necessario impostare almeno le proprietà di associazione InboundOperationType, PollingStatement e PollingInterval . Per questo esempio, si imposta anche la proprietà di associazione PostPollStatement . Per altre informazioni sulle proprietà di associazione usate per configurare il polling, vedere Ricevere messaggi di modifica dei dati basati sul polling nell'adapter Oracle Database.

    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. Creare una raccolta di parametri di associazione e impostare le credenziali.

    ClientCredentials credentials = new ClientCredentials();  
    credentials.UserName.UserName = "SCOTT";  
    credentials.UserName.Password = "TIGER";  
    
    BindingParameterCollection bindingParams = new BindingParameterCollection();  
    bindingParams.Add(credentials);  
    
  6. Creare un listener del canale e aprirlo. Per creare il listener, richiamare il metodo BuildChannelListener<IInputChannel> in OracleDBBinding. È possibile modificare lo spazio dei nomi di destinazione per l'operazione POLLINGSTMT impostando la proprietà PollingId nell'URI di connessione. Per ulteriori informazioni sull'URI di connessione dell'adapter, vedere Vedere l'URI di connessione di Oracle Database.

    IChannelListener<IInputChannel> listener = binding.BuildChannelListener<IInputChannel>(connectionUri, bindingParams);  
    listener.Open();  
    
  7. Ottenere un canale IInputChannel richiamando il metodo AcceptChannel nel listener e aprirlo.

    IInputChannel channel = listener.AcceptChannel();  
    channel.Open();  
    
  8. Richiamare Receive sul canale per ottenere il successivo messaggio POLLINGSTMT dall'adapter.

    Message message = channel.Receive();  
    
  9. Consumare il set di risultati restituito dall'operazione POLLINGSTMT. È possibile utilizzare il messaggio usando xmlReader o XmlDictionaryWriter.

    XmlReader reader = message.GetReaderAtBodyContents();  
    
  10. Chiudere il canale dopo aver completato l'elaborazione della richiesta.

    channel.Close()  
    

    Importante

    Dopo aver completato l'elaborazione dell'operazione POLLINGSTMT, è necessario chiudere il canale. La mancata chiusura del canale può influire sul comportamento del codice.

  11. Chiudi il listener quando hai finito di ricevere messaggi di variazione dei dati.

    listener.Close()  
    

    Importante

    La chiusura del listener non chiude i canali creati usando il listener. È necessario chiudere in modo esplicito ogni canale creato usando il listener.

Esempio

Nell'esempio seguente viene illustrato come configurare l'adapter Oracle Database per eseguire il polling di viste e tabelle di database Oracle e ricevere l'operazione POLLLINGSTMT usando il modello di canale WCF. Il set di risultati restituito nell'operazione POLLINGSTMT viene scritto nella console usando un XmlReader.

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

Vedere anche

Sviluppare applicazioni Oracle Database usando il modello di canale WCF