Compartir a través de


Recepción de mensajes con cambios de datos basados en sondeo fuertemente tipados de SQL Server mediante el modelo de servicio WCF

Puede configurar el adaptador de SQL para recibir mensajes de sondeo fuertemente tipados de SQL Server. 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. Debe usar sondeos fuertemente tipados en un escenario en el que quiera recibir un conjunto de resultados fuertemente tipado. Para obtener más información sobre cómo el adaptador admite sondeos fuertemente tipados, consulte Compatibilidad con llamadas entrantes mediante sondeo.

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 fuertemente tipados, cree una aplicación .NET y genere el contrato de servicio WCF para la operación TypedPolling . Asegúrese de especificar lo siguiente al generar el contrato de servicio WCF:

  • Debe especificar un InboundID como parte del URI de conexión.

  • Debe especificar una instrucción de sondeo para la propiedad de enlace PollingStatement .

    Además, si desea especificar otras propiedades de enlace relacionadas con el sondeo al generar la clase proxy, 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 al generar el contrato de servicio WCF y las clases auxiliares:

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 del sondeo con tipo 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. Aparte de la propiedad de enlace PollingStatement , se requieren todas las demás propiedades de enlace enumeradas en esta sección mientras se ejecuta la aplicación .NET. Debe especificar la propiedad de enlace PollingStatement antes de generar la operación TypedPolling del contrato de servicio WCF.

Binding (propiedad) Descripción
InboundOperationType Especifica si desea realizar la operación de entrada Polling, TypedPolling o Notification . El valor predeterminado es Sondeo. Para recibir mensajes de sondeo fuertemente tipados, establezca este valor en TypedPolling.
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. Importante: Para TypedPolling, debe especificar esta propiedad de enlace antes de generar metadatos.
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.

Configurar sondeo fuertemente tipado 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 TypedPolling a partir de los metadatos expuestos por el adaptador. Para ello, puede usar el complemento Agregar referencia del servicio adaptador de Visual Studio. Al generar el contrato de servicio WCF para este ejemplo, asegúrese de:

    • Especifique inboundID como Employee.

    • Especifique una instrucción de sondeo para la propiedad de enlace PollingStatement . En este ejemplo, especifique la instrucción de sondeo como:

      SELECT * FROM Employee;EXEC MOVE_EMP_DATA;EXEC ADD_EMP_DETAILS John, Tester, 100000
      
  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, TypedPolling_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 de servicio de adaptador para crear un contrato de servicio WCF (interfaz) y clases auxiliares para la operación TypedPolling . 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 TypedPolling .

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

    // CODEGEN: Generating message contract since the wrapper namespace (https://schemas.microsoft.com/Sql/2008/05/TypedPolling/Employee) of message TypedPolling
    // does not match the default value (https://schemas.microsoft.com/Sql/2008/05/)
    [System.ServiceModel.OperationContractAttribute(IsOneWay=true, Action="TypedPolling")]
    void TypedPolling(TypedPolling 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, especificó el identificador de entrada como Employee. El mensaje de solicitud devuelve un conjunto de resultados fuertemente tipado.

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

[System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://schemas.microsoft.com/Sql/2008/05/TypedPolling/Employee", Order=0)]
    public schemas.microsoft.com.Sql._2008._05.TypedPolling.Employee.TypedPollingResultSet0[] TypedPollingResultSet0;

[System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://schemas.microsoft.com/Sql/2008/05/TypedPolling/Employee", Order=1)]
    public schemas.microsoft.com.Sql._2008._05.TypedPolling.Employee.TypedPollingResultSet1[] TypedPollingResultSet1;

    public TypedPolling() {
    }

    public TypedPolling(schemas.microsoft.com.Sql._2008._05.TypedPolling.Employee.TypedPollingResultSet0[] TypedPollingResultSet0, schemas.microsoft.com.Sql._2008._05.TypedPolling.Employee.TypedPollingResultSet1[] TypedPollingResultSet1) {
        this.TypedPollingResultSet0 = TypedPollingResultSet0;
        this.TypedPollingResultSet1 = TypedPollingResultSet1;
    }
}

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 TypedPolling 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 : TypedPolling_Employee {

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

Recepción de mensajes entrantes fuertemente tipados 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 de entrada fuertemente tipados mediante el 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 TypedPolling . Asegúrese de especificar lo siguiente al generar el contrato de servicio WCF para este ejemplo:

    • Debe especificar inboundID como Employee.

    • Debe especificar una instrucción de sondeo para la propiedad de enlace PollingStatement . En este ejemplo, especifique la instrucción de sondeo como:

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

      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 TypedPolling de esta clase puede producir una excepción para anular la transacción de sondeo, si se encuentra un error al procesar los datos recibidos de la operación TypedPolling ; 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 TypedPolling , puede implementar la lógica de la aplicación directamente. Esta clase se puede encontrar en SqlAdapterBindingService.cs. Este código de esta subclase de ejemplo es la clase SqlAdapterBindingService . En este código, el mensaje de sondeo recibido como un conjunto de resultados fuertemente tipado se escribe en la consola.

    [ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]
    
    public class PollingService : SqlAdapterBindingNamespace.SqlAdapterBindingService
    {
        public override void TypedPolling(TypedPolling request)
        {
            Console.WriteLine("\nNew Polling Records Received");
            Console.WriteLine("*************************************************");
            Console.WriteLine("Employee ID\tName\tDesignation\tSalary");
    
            for (int i = 0; i < request.TypedPollingResultSet0.Length; i++)
            {
                Console.WriteLine("{0}\t{1}\t{2}\t{3}",
                request.TypedPollingResultSet0[i].Employee_ID,
                request.TypedPollingResultSet0[i].Name,
                request.TypedPollingResultSet0[i].Designation,
                request.TypedPollingResultSet0[i].Salary);
            }
            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 una instancia de 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.TypedPolling;
    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. 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 "TypedPolling_Employee".

    // Add service endpoint: be sure to specify TypedPolling_Employee as the contract
    Uri ConnectionUri = new Uri("mssql://mysqlserver//mydatabase?InboundID=Employee");
    serviceHost.AddServiceEndpoint("TypedPolling_Employee", binding, ConnectionUri);
    
  9. Para recibir datos de sondeo, abra el host de 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 de 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 MOVE_EMP_DATA procedimiento almacenado para mover todos los registros de la tabla Employee a la tabla 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;

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

    public class PollingService : SqlAdapterBindingNamespace.SqlAdapterBindingService
    {
        public override void TypedPolling(TypedPolling request)
        {
            Console.WriteLine("\nNew Polling Records Received");
            Console.WriteLine("*************************************************");
            Console.WriteLine("Employee ID\tName\tDesignation\tSalary");

            for (int i = 0; i < request.TypedPollingResultSet0.Length; i++)
            {
                Console.WriteLine("{0}\t{1}\t{2}\t{3}",
                request.TypedPollingResultSet0[i].Employee_ID,
                request.TypedPollingResultSet0[i].Name,
                request.TypedPollingResultSet0[i].Designation,
                request.TypedPollingResultSet0[i].Salary);
            }
            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.TypedPolling;
                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 that was used to generate
                // the WCF service callback interface
                Uri ConnectionUri = new Uri("mssql://mysqlserver//mydatabase?InboundId=Employee");

                // This URI is used to initialize the ServiceHost. It cannot contain
                // the 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("TypedPolling_Employee", 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