Recepción de mensajes modificados por datos basados en sondeo en la base de datos de Oracle mediante el modelo de canal WCF
Puede configurar el adaptador de Microsoft BizTalk para oracle Database para sondear una tabla de base de datos de Oracle o ver los cambios de datos. Para realizar esta operación de sondeo, el adaptador ejecuta periódicamente una consulta SQL en una tabla o vista de Oracle seguida de un bloque de código PL/SQL opcional. A continuación, el adaptador de Oracle Database devuelve los resultados de la consulta SQL al código como un conjunto de resultados fuertemente tipado en una operación POLLINGSTMT entrante. Para obtener más información sobre el mecanismo utilizado para configurar y realizar sondeos en una base de datos de Oracle mediante el adaptador de Oracle Database, consulte Recepción de mensajes modificados por datos basados en sondeo en el adaptador de Oracle Database. Se recomienda encarecidamente leer este tema antes de continuar.
Configure el adaptador de Oracle Database para sondear y ver la tabla o vista de base de datos de Oracle estableciendo propiedades de enlace en una instancia de OracleDBBinding. En el modelo de canal WCF, usará este enlace para crear un agente de escucha de canal desde el que puede obtener un canal IInputChannel para recibir la operación POLLINGSTMT del adaptador.
Para obtener información general sobre cómo recibir operaciones mediante IInputChannel en WCF, consulte Programación de Service Channel-Level.
En las secciones de este tema se proporciona información para ayudarle a realizar sondeos en tablas y vistas de base de datos de Oracle mediante el modelo de canal WCF.
Consumo del mensaje de solicitud POLLINGSTMT
El adaptador invoca la operación POLLINGSTMT en el código para sondear la base de datos de Oracle. Es decir, el adaptador envía un mensaje de solicitud POLLINGSTMT que recibe a través de una forma de canal IInputChannel . El mensaje de solicitud POLLINGSTMT contiene el conjunto de resultados de la consulta especificada por la propiedad de enlace PollingStatement . Puede consumir el mensaje POLLINGSTMT de una de estas dos maneras:
Para consumir el mensaje mediante streaming de valor de nodo, debe llamar al método WriteBodyContents en el mensaje de respuesta y pasarlo un XmlDictionaryWriter que implemente streaming de valor de nodo.
Para consumir el mensaje mediante streaming de nodos, puede llamar a GetReaderAtBodyContents en el mensaje de respuesta para obtener un xmlReader.
Normalmente, se usa el streaming de nodo-valor para consumir conjuntos de resultados que contienen columnas de datos loB de Oracle.
Para obtener más información sobre la estructura de mensajes de la operación POLLINGSTMT, vea Esquemas de mensaje para las operaciones de sondeo.
Para obtener más información sobre cómo el adaptador de Oracle Database admite el streaming en datos LOB, consulte Streaming de tipos de datos de objetos grandes en el adaptador de Oracle Database.
Para obtener más información sobre cómo implementar el streaming de nodo-valor en el código para admitir el streaming de datos lob de un extremo a otro, vea Streaming de tipos de datos lob de base de datos de Oracle mediante el modelo de canal WCF.
Acerca de los ejemplos usados en este tema
En el ejemplo de este tema se usa SCOTT. Tabla ACCOUNTACTIVITY y SCOTT. ACCOUNT_PKG. PROCESS_ACTIVITY función. Se proporciona un script para generar estos artefactos con los ejemplos. En el ejemplo se realizan las siguientes operaciones:
Como parte de la instrucción de sondeo, selecciona todos los registros de la tabla ACCOUNTACTIVITY y se muestra en la consola.
Como parte de la instrucción post poll, el ejemplo invoca la función PROCESS_ACTIVITY que mueve todos los registros de la tabla ACCOUNTACTIVITY a la tabla ACTIVITYHISTORY.
Los sondeos posteriores de la tabla ACCOUNTACTIVITY no devuelven ningún registro. Sin embargo, si desea que el ejemplo devuelva más registros como parte de la operación de sondeo, debe insertar algunos registros en la tabla ACCOUNTACTIVITY. Para ello, ejecute el script more_activity_data.sql proporcionado con los ejemplos.
Para obtener más información sobre los ejemplos, vea Ejemplos de adaptador.
¿Cómo se sondea una base de datos de Oracle mediante un IInputChannel?
Para sondear una tabla o vista de base de datos de Oracle para recibir mensajes de cambio de datos mediante el modelo de canal WCF, realice los pasos siguientes.
Para recibir mensajes modificados por datos mediante IInputChannel
Cree un proyecto de Visual C# en Visual Studio. Para este tema, cree una aplicación de consola.
En el Explorador de soluciones, agregue referencia a
Microsoft.Adapters.OracleDB
,Microsoft.ServiceModel.Channels
,System.ServiceModel
ySystem.Runtime.Serialization
.Abra el archivo Program.cs y agregue los siguientes espacios de nombres:
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
Cree una instancia de OracleDBBinding y establezca las propiedades de enlace necesarias para configurar el sondeo. Como mínimo, debe establecer las propiedades de enlace InboundOperationType, PollingStatement y PollingInterval . En este ejemplo, también se establece la propiedad de enlace PostPollStatement . Para obtener más información sobre las propiedades de enlace usadas para configurar el sondeo, consulte Recepción de mensajes modificados por datos basados en sondeos en el adaptador de 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;"
Cree una colección de parámetros de enlace y establezca las credenciales.
ClientCredentials credentials = new ClientCredentials(); credentials.UserName.UserName = "SCOTT"; credentials.UserName.Password = "TIGER"; BindingParameterCollection bindingParams = new BindingParameterCollection(); bindingParams.Add(credentials);
Cree un agente de escucha de canal y ábralo. Para crear el agente de escucha, invoque el método BuildChannelListener<IInputChannel> en OracleDBBinding. Puede modificar el espacio de nombres de destino para la operación POLLINGSTMT estableciendo la propiedad PollingId en el URI de conexión. Para obtener más información sobre el URI de conexión del adaptador, consulte Creación del URI de conexión de Oracle Database.
IChannelListener<IInputChannel> listener = binding.BuildChannelListener<IInputChannel>(connectionUri, bindingParams); listener.Open();
Obtenga un canal IInputChannel invocando el método AcceptChannel en el agente de escucha y ábralo.
IInputChannel channel = listener.AcceptChannel(); channel.Open();
Invoque Receive en el canal para obtener el siguiente mensaje POLLINGSTMT del adaptador.
Message message = channel.Receive();
Consuma el conjunto de resultados devuelto por la operación POLLINGSTMT. Puede consumir el mensaje mediante XmlReader o XmlDictionaryWriter.
XmlReader reader = message.GetReaderAtBodyContents();
Cierre el canal cuando haya completado el procesamiento de la solicitud.
channel.Close()
Importante
Debe cerrar el canal una vez que haya terminado de procesar la operación POLLINGSTMT. Si no se cierra el canal, puede afectar al comportamiento del código.
Cierre el agente de escucha cuando haya terminado de recibir mensajes modificados por datos.
listener.Close()
Importante
Cerrar el agente de escucha no cierra los canales creados mediante el agente de escucha. Debe cerrar explícitamente cada canal creado mediante el agente de escucha.
Ejemplo
En el ejemplo siguiente se muestra cómo configurar el adaptador de base de datos de Oracle para sondear las tablas y vistas de base de datos de Oracle y recibir la operación POLLLINGSTMT mediante el modelo de canal WCF. El conjunto de resultados devuelto en la operación POLLINGSTMT se escribe en la consola mediante 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();
}
}
}
}
}
Consulte también
Desarrollo de aplicaciones de Oracle Database mediante el modelo de canal WCF