Compartir a través de


Recepción de mensajes modificados por datos basados en sondeos de SQL Server mediante el modelo de servicio WCF

Puede configurar el adaptador de SQL para recibir mensajes periódicos de cambio de datos para SQL Server tablas o vistas. Puede especificar una instrucción de sondeo que el adaptador ejecuta para sondear la base de datos. La instrucción de sondeo puede ser una instrucción SELECT o un procedimiento almacenado que devuelve un conjunto de resultados.

Para obtener más información sobre cómo el adaptador admite el sondeo, consulte Sondeo en SQL Server mediante el adaptador de SQL.

Nota

En este tema se muestra cómo usar la operación de entrada de sondeo para usar mensajes de sondeo. El mensaje de la operación de sondeo no está fuertemente tipado. Si desea obtener un mensaje de sondeo fuertemente tipado, debe usar la operación TypedPolling . También debe usar la operación TypedPolling para tener varias operaciones de sondeo en una sola aplicación. Para obtener instrucciones sobre cómo realizar la operación TypedPolling, vea Recibir mensajes con cambios de datos basados en sondeo fuertemente tipados de SQL Server mediante el modelo de servicio WCF.

Importante

Si desea tener más de una operación de sondeo en una sola aplicación, debe especificar una propiedad de conexión InboundID como parte del URI de conexión para que sea única. El identificador de entrada que especifique se agrega al espacio de nombres de la operación para que sea único.

Cómo muestra este tema el sondeo

En este tema, para demostrar cómo el adaptador de SQL admite la recepción de mensajes de cambio de datos, cree una aplicación .NET y genere el contrato de servicio WCF para la operación de sondeo . Si desea especificar las propiedades de enlace relacionadas con el sondeo al generar el contrato de servicio WCF, especifique PolledDataAvailableStatement como:

SELECT COUNT(*) FROM Employee

PolledDataAvailableStatement debe devolver un conjunto de resultados con la primera celda que contiene un valor positivo. Si la primera celda no contiene un valor positivo, el adaptador no ejecuta la instrucción de sondeo.

Como parte de la instrucción de sondeo, realice las siguientes operaciones:

  1. Seleccione todas las filas de la tabla Empleado.

  2. Ejecute un procedimiento almacenado (MOVE_EMP_DATA) para mover todos los registros de la tabla Employee a una tabla EmployeeHistory.

  3. Ejecute un procedimiento almacenado (ADD_EMP_DETAILS) para agregar un nuevo registro a la tabla Employee. Este procedimiento toma el nombre del empleado, la designación y el salario como parámetros.

    Para realizar estas operaciones, debe especificar lo siguiente para la propiedad de enlace PollingStatement :

SELECT * FROM Employee;EXEC MOVE_EMP_DATA;EXEC ADD_EMP_DETAILS John, Tester, 100000

Una vez ejecutada la instrucción de sondeo, se seleccionan todos los registros de la tabla Employee y se recibe el mensaje de SQL Server. Una vez ejecutado el MOVE_EMP_DATA procedimiento almacenado por el adaptador, todos los registros se mueven a la tabla EmployeeHistory. A continuación, el ADD_EMP_DETAILS procedimiento almacenado se ejecuta para agregar un nuevo registro a la tabla Employee. La siguiente ejecución de sondeo solo devolverá un único registro. Este ciclo continúa hasta que se cierra el host de servicio.

Configuración de una consulta de sondeo con las propiedades de enlace del adaptador de SQL

En la tabla siguiente se resumen las propiedades de enlace del adaptador de SQL que se usan para configurar el adaptador para recibir mensajes de cambio de datos. Debe especificar estas propiedades de enlace como parte de la aplicación .NET para sondear.

Binding (propiedad) Descripción
InboundOperationType Especifica si desea realizar la operación de entrada Polling, TypedPolling o Notification . El valor predeterminado es Sondeo.
PolledDataAvailableStatement Especifica la instrucción SQL que ejecuta el adaptador para determinar si hay datos disponibles para el sondeo. La instrucción SQL debe devolver un conjunto de resultados que consta de filas y columnas. Solo si hay una fila disponible, se ejecutará la instrucción SQL especificada para la propiedad de enlace PollingStatement .
PollingIntervalInSeconds Especifica el intervalo, en segundos, en el que el adaptador de SQL ejecuta la instrucción especificada para la propiedad de enlace PolledDataAvailableStatement . El valor predeterminado es 30 segundos. El intervalo de sondeo determina el intervalo de tiempo entre sondeos sucesivos. Si la instrucción se ejecuta dentro del intervalo especificado, el adaptador espera el tiempo restante en el intervalo.
PollingStatement Especifica la instrucción SQL que se va a sondear la tabla de base de datos SQL Server. Puede especificar una instrucción SELECT simple o un procedimiento almacenado para la instrucción de sondeo. El valor predeterminado es null. Debe especificar un valor para PollingStatement para habilitar el sondeo. La instrucción de sondeo solo se ejecuta si hay datos disponibles para el sondeo, que viene determinado por la propiedad de enlace PolledDataAvailableStatement . Puede especificar cualquier número de instrucciones SQL separadas por punto y coma.
PollWhileDataFound Especifica si el adaptador de SQL omite el intervalo de sondeo y ejecuta continuamente la instrucción SQL especificada para la propiedad de enlace PolledDataAvailableStatement , si los datos están disponibles en la tabla que se están sondeando. Si no hay datos disponibles en la tabla, el adaptador revierte para ejecutar la instrucción SQL en el intervalo de sondeo especificado. El valor predeterminado es false.

Para obtener una descripción más completa de estas propiedades, vea Leer sobre el adaptador de BizTalk para SQL Server propiedades de enlace del adaptador. Para obtener una descripción completa de cómo usar el adaptador de SQL para sondear SQL Server, lea más información.

Configuración del sondeo en el modelo de servicio WCF

Para recibir la operación de sondeo al usar el modelo de servicio WCF, debe hacer lo siguiente:

  1. Genere un contrato de servicio WCF (interfaz) para la operación de sondeo a partir de los metadatos expuestos por el adaptador. Para ello, puede usar el complemento Agregar referencia del servicio adaptador de Visual Studio.

  2. Implemente un servicio WCF desde esta interfaz.

  3. Hospede este servicio WCF mediante un host de servicio (System.ServiceModel.ServiceHost).

Acerca de los ejemplos usados en este tema

Los ejemplos de este tema sondean la tabla Employee. En el ejemplo también se usa el MOVE_EMP_DATA y ADD_EMP_DETAILS procedimiento almacenado. Se proporciona un script para generar estos artefactos con los ejemplos. Para obtener más información sobre los ejemplos, vea Ejemplos para el adaptador de SQL. También se proporciona un ejemplo, Polling_ServiceModel, que se basa en este tema, con los ejemplos del adaptador de SQL.

Contrato y clase de servicio WCF

Puede usar el complemento Agregar referencia del servicio adaptador para crear un contrato de servicio WCF (interfaz) y clases auxiliares para la operación de sondeo . Para obtener más información sobre cómo generar un contrato de servicio WCF, vea Generar un cliente WCF o un contrato de servicio WCF para SQL Server Artefactos.

El contrato de servicio WCF (interfaz)

En el código siguiente se muestra el contrato de servicio WCF (interfaz) generado para la operación de sondeo .

[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "3.0.0.0")]
[System.ServiceModel.ServiceContractAttribute(Namespace="http://schemas.microsoft.com/Sql/2008/05/", ConfigurationName="PollingOperation")]
public interface PollingOperation {

    // CODEGEN: Generating message contract since the wrapper namespace (https://schemas.microsoft.com/Sql/2008/05/Polling/) of message Polling
    // does not match the default value (https://schemas.microsoft.com/Sql/2008/05/)
    [System.ServiceModel.OperationContractAttribute(IsOneWay=true, Action="Polling")]
    [System.ServiceModel.XmlSerializerFormatAttribute()]
    void Polling(Polling request);
}

Contratos de mensaje

El espacio de nombres del contrato de mensaje se modifica mediante el parámetro InboundID en el URI de conexión, si se especifica. En este ejemplo, no especificó un identificador de entrada en el URI de conexión. El mensaje de solicitud devuelve un objeto DataSet.

[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "3.0.0.0")]
[System.ServiceModel.MessageContractAttribute(WrapperName="Polling", WrapperNamespace="http://schemas.microsoft.com/Sql/2008/05/Polling/", IsWrapped=true)]
public partial class Polling {

[System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://schemas.microsoft.com/Sql/2008/05/Polling/", Order=0)]
    [System.Xml.Serialization.XmlArrayAttribute(IsNullable=true)]
    [System.Xml.Serialization.XmlArrayItemAttribute("DataSet", Namespace="http://schemas.datacontract.org/2004/07/System.Data", IsNullable=false)]
    public System.Data.DataSet[] PolledData;

    public Polling() {
    }

    public Polling(System.Data.DataSet[] PolledData) {
        this.PolledData = PolledData;
    }
}

Clase de servicio WCF

El complemento Add Adapter Service Reference también genera un archivo que tiene un código auxiliar para la clase de servicio WCF implementada a partir del contrato de servicio (interfaz). El nombre del archivo es SqlAdapterBindingService.cs. Puede insertar la lógica para procesar la operación de sondeo directamente en esta clase. En el código siguiente se muestra la clase de servicio WCF generada por el complemento Agregar referencia del servicio adaptador.

namespace SqlAdapterBindingNamespace {

    public class SqlAdapterBindingService : PollingOperation {

        // CODEGEN: Generating message contract since the wrapper namespace (https://schemas.microsoft.com/Sql/2008/05/Polling/) of message Polling
        // does not match the default value (https://schemas.microsoft.com/Sql/2008/05/)
        public virtual void Polling(Polling request) {
            throw new System.NotImplementedException("The method or operation is not implemented.");
        }
    }
}

Recepción de mensajes entrantes para la operación de sondeo

En esta sección se proporcionan instrucciones sobre cómo escribir una aplicación .NET para recibir mensajes de sondeo entrantes mediante el adaptador de SQL.

Para recibir mensajes de sondeo del adaptador de SQL

  1. Use el complemento Agregar referencia del servicio adaptador para generar un contrato de servicio WCF (interfaz) y clases auxiliares para la operación de sondeo . Para obtener más información, vea Generar un cliente WCF o un contrato de servicio WCF para SQL Server artefactos. Opcionalmente, puede especificar las propiedades de enlace al generar el contrato de servicio y las clases auxiliares. Esto garantiza que se establecen correctamente en el archivo de configuración generado.

  2. Implemente un servicio WCF desde la interfaz y las clases auxiliares generadas en el paso 1. El método Polling de esta clase puede producir una excepción para anular la transacción de sondeo, si se produce un error al procesar los datos recibidos de la operación de sondeo ; de lo contrario, el método no devuelve nada. Debe atribuir la clase de servicio WCF de la siguiente manera:

    [ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]
    

    Dentro del método Polling , puede implementar la lógica de la aplicación directamente. Esta clase se puede encontrar en SqlAdapterBindingService.cs. Este código de este ejemplo subclase la clase SqlAdapterBindingService . En este código, el mensaje de sondeo recibido como dataset se escribe en la consola.

    [ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]
    
    public class PollingService : SqlAdapterBindingNamespace.SqlAdapterBindingService
    {
    
    public override void Polling(Polling request)
    {
        Console.WriteLine("\nNew Polling Records Received");
        Console.WriteLine("*************************************************");
        DataSet[] dataArray = request.PolledData;
        foreach (DataTable tab in dataArray[0].Tables)
        {
            foreach (DataRow row in tab.Rows)
            {
                for (int i = 0; i < tab.Columns.Count; i++)
                {
                    Console.WriteLine(row[i]);
                }
            }
        }
        Console.WriteLine("*************************************************");
        Console.WriteLine("\nHit <RETURN> to stop polling");
        }
    }
    
  3. Dado que el adaptador de SQL no acepta credenciales como parte del URI de conexión, debe implementar la siguiente clase para pasar credenciales para la base de datos de SQL Server. En la última parte de la aplicación, creará una instancia de esta clase para pasar las credenciales de SQL Server.

    class PollingCredentials : ClientCredentials, IServiceBehavior
    {
        public void AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase, Collection<ServiceEndpoint> endpoints, BindingParameterCollection bindingParameters)
        {
            bindingParameters.Add(this);
        }
    
        public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
        { }
    
        public void Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
        { }
    
        protected override ClientCredentials CloneCore()
        {
            ClientCredentials clone = new PollingCredentials();
            clone.UserName.UserName = this.UserName.UserName;
            clone.UserName.Password = this.UserName.Password;
            return clone;
        }
    }
    
  4. Cree sqlAdapterBinding y configure la operación de sondeo especificando las propiedades de enlace. Puede hacerlo explícitamente en el código o mediante declaración en la configuración. Como mínimo, debe especificar InboundOperationType, PolledDataAvailableStatement y PollingStatement.

    SqlAdapterBinding binding = new SqlAdapterBinding();
    binding.InboundOperationType = InboundOperation.Polling;
    binding.PolledDataAvailableStatement = "SELECT COUNT (*) FROM EMPLOYEE";
    binding.PollingStatement = "SELECT * FROM Employee;EXEC MOVE_EMP_DATA;EXEC ADD_EMP_DETAILS John, Tester, 100000";
    
  5. Especifique SQL Server credenciales de base de datos creando instancias de la clase PollingCredentials que creó en el paso 3.

    PollingCredentials credentials = new PollingCredentials();
    credentials.UserName.UserName = "<Enter user name here>";
    credentials.UserName.Password = "<Enter password here>";
    
  6. Cree una instancia del servicio WCF creado en el paso 2.

    // create service instance
    PollingService service = new PollingService();
    
  7. Cree una instancia de System.ServiceModel.ServiceHost mediante el servicio WCF y un URI de conexión base. El URI de conexión base no puede contener el identificador de entrada, si se especifica. También debe especificar las credenciales aquí.

    // Enable service host
    Uri[] baseUri = new Uri[] { new Uri("mssql://mysqlserver//mydatabase") };
    ServiceHost serviceHost = new ServiceHost(service, baseUri);
    serviceHost.Description.Behaviors.Add(credentials);
    
    
  8. Agregue un punto de conexión de servicio al host de servicio. Para ello, siga estos pasos:

    • Use el enlace creado en el paso 4.

    • Especifique un URI de conexión que contenga credenciales y, si es necesario, un identificador de entrada.

    • Especifique el contrato como "PollingOperation".

    // Add service endpoint: be sure to specify PollingOperation as the contract
    Uri ConnectionUri = new Uri("mssql://mysqlserver//mydatabase?");
    serviceHost.AddServiceEndpoint("PollingOperation", binding, ConnectionUri);
    
  9. Para recibir datos de sondeo, abra el host del servicio. El adaptador devolverá datos cada vez que la consulta devuelva un conjunto de resultados.

    // Open the service host to begin polling
    serviceHost.Open();
    
  10. Para finalizar el sondeo, cierre el host del servicio.

    Importante

    El adaptador seguirá sondeando hasta que se cierre el host de servicio.

    serviceHost.Close();
    

Ejemplo

En el ejemplo siguiente se muestra una consulta de sondeo que ejecuta la tabla Employee. La instrucción de sondeo realiza las siguientes tareas:

  1. Selecciona todos los registros de la tabla Employee.

  2. Ejecuta el procedimiento almacenado MOVE_EMP_DATA para mover todos los registros de la tabla Employee a employeeHistory.

  3. Ejecuta el ADD_EMP_DETAILS procedimiento almacenado para agregar un único registro a la tabla Employee.

    El primer mensaje de sondeo contendrá todos los registros de la tabla Employee. Los mensajes de sondeo posteriores contendrán solo el último registro insertado por el ADD_EMP_DETAILS procedimiento almacenado. El adaptador seguirá sondeando hasta que cierre el host de servicio presionando <RETURN>.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using Microsoft.Adapters.Sql;
using Microsoft.ServiceModel.Channels;
using System.ServiceModel;
using System.ServiceModel.Description;
using System.ServiceModel.Channels;
using System.Collections.ObjectModel;
using System.Data;

namespace Polling_ServiceModel
{
    [ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]

    public class PollingService : SqlAdapterBindingNamespace.SqlAdapterBindingService
    {

        public override void Polling(Polling request)
        {
            Console.WriteLine("\nNew Polling Records Received");
            Console.WriteLine("*************************************************");
            DataSet[] dataArray = request.PolledData;
            foreach (DataTable tab in dataArray[0].Tables)
            {
                foreach (DataRow row in tab.Rows)
                {
                    for (int i = 0; i < tab.Columns.Count; i++)
                    {
                        Console.WriteLine(row[i]);
                    }
                }
            }
            Console.WriteLine("*************************************************");
            Console.WriteLine("\nHit <RETURN> to stop polling");
        }
    }

    class PollingCredentials : ClientCredentials, IServiceBehavior
    {
        public void AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase, Collection<ServiceEndpoint> endpoints, BindingParameterCollection bindingParameters)
        {
            bindingParameters.Add(this);
        }

        public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
        { }

        public void Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
        { }

        protected override ClientCredentials CloneCore()
        {
            ClientCredentials clone = new PollingCredentials();
            clone.UserName.UserName = this.UserName.UserName;
            clone.UserName.Password = this.UserName.Password;
            return clone;
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            ServiceHost serviceHost = null;
            try
            {
                Console.WriteLine("Sample started...");
                Console.WriteLine("Press any key to start polling...");
                Console.ReadLine();

                SqlAdapterBinding binding = new SqlAdapterBinding();
                binding.InboundOperationType = InboundOperation.Polling;
                binding.PolledDataAvailableStatement = "SELECT COUNT (*) FROM EMPLOYEE";
                binding.PollingStatement = "SELECT * FROM Employee;EXEC MOVE_EMP_DATA;EXEC ADD_EMP_DETAILS John, Tester, 100000";
                Console.WriteLine("Binding properties assigned...");

                // This URI is used to specify the address for the ServiceEndpoint
                // It must contain the InboundId (if any) that was used to generate
                // the WCF service callback interface
                Uri ConnectionUri = new Uri("mssql://mysqlserver//mydatabase?");

                // This URI is used to initialize the ServiceHost. It cannot contain
                // a query_string (InboundID); otherwise,an exception is thrown when
                // the ServiceHost is initialized.
                Uri[] baseUri = new Uri[] { new Uri("mssql://mysqlserver//mydatabase") };

                PollingCredentials credentials = new PollingCredentials();
                credentials.UserName.UserName = "<Enter user name here>";
                credentials.UserName.Password = "<Enter password here>";

                Console.WriteLine("Opening service host...");
                PollingService service = new PollingService();
                serviceHost = new ServiceHost(service, baseUri);
                serviceHost.Description.Behaviors.Add(credentials);
                serviceHost.AddServiceEndpoint("PollingOperation", binding, ConnectionUri);
                serviceHost.Open();
                Console.WriteLine("Service host opened...");
                Console.WriteLine("Polling started...");
                Console.ReadLine();
            }
            catch (Exception e)
            {
                Console.WriteLine("Exception :" + e.Message);
                Console.ReadLine();

                /* If there is an error it will be specified in the inner exception */
                if (e.InnerException != null)
                {
                    Console.WriteLine("InnerException: " + e.InnerException.Message);
                    Console.ReadLine();
                }
            }
            finally
            {
                // IMPORTANT: you must close the ServiceHost to stop polling
                if (serviceHost.State == CommunicationState.Opened)
                    serviceHost.Close();
                else
                    serviceHost.Abort();
            }
        }
    }
}

Consulte también

Sondear SQL Server mediante el adaptador de SQL con el modelo de servicio WCF