Compartir a través de


Recepción de notificaciones de consulta de SQL mediante el modelo de servicio WCF

En este tema se muestra cómo configurar el adaptador de SQL para recibir mensajes de notificación de consulta de una base de datos de SQL Server. Para demostrar las notificaciones, considere una tabla, Employee, con una columna "Status". Cuando se inserta un nuevo registro en esta tabla, el valor de la columna Estado se establece en 0. Puede configurar el adaptador para recibir notificaciones registrando las notificaciones mediante una instrucción SQL que recupera todos los registros que tienen la columna Estado como "0". Para ello, especifique la instrucción SQL para la propiedad de enlace NotificationStatement . Una vez que el cliente del adaptador recibe la notificación, puede contener la lógica para realizar cualquier tarea posterior en la base de datos SQL Server. En este ejemplo, por motivos de simplicidad, el cliente del adaptador muestra todos los registros de la tabla que tienen la columna Status como "0".

Nota

Si está realizando operaciones en tablas que tienen columnas de tipos definidos por el usuario, asegúrese de consultar Operaciones en tablas y vistas con tipos definidos por el usuario mediante el tema adaptador de SQL antes de empezar a desarrollar la aplicación.

Configuración de notificaciones 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 la recepción de notificaciones de SQL Server. Debe especificar estas propiedades de enlace mientras ejecuta la aplicación .NET para recibir las notificaciones de una base de datos de SQL Server.

Binding (propiedad) Descripción
InboundOperationType Especifica la operación de entrada que desea realizar. Para recibir mensajes de notificación, establezca esta opción en Notificación.
NotificationStatement Especifica la instrucción SQL (procedimiento> almacenado SELECT o EXEC<) que se usa para registrarse para las notificaciones de consulta. El adaptador obtiene un mensaje de notificación de SQL Server solo cuando cambia el conjunto de resultados de la instrucción SQL especificada.
NotifyOnListenerStart Especifica si el adaptador envía una notificación a los clientes del adaptador cuando se inicia el agente de escucha.

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 recibir notificaciones de SQL Server, lea más información.

Configuración de notificaciones mediante el modelo de servicio WCF

Para recibir las notificaciones mediante el modelo de servicio WCF, debe hacer lo siguiente:

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

  2. Genere un cliente WCF para la operación Select en la tabla Employee ( Empleado). Para ello, puede usar el complemento Agregar referencia del servicio adaptador.

  3. Implemente un servicio WCF desde esta interfaz.

  4. 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 reciben una notificación para la tabla Employee. Se proporciona un script para generar la tabla 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, Notification_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 de notificación . 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 notificación .

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

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

Contratos de mensaje

A continuación se muestra el contrato de mensaje para la operación notificación.

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

    [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://schemas.microsoft.com/Sql/2008/05/Notification/", Order=0)]
    public string Info;

    [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://schemas.microsoft.com/Sql/2008/05/Notification/", Order=1)]
    public string Source;

    [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://schemas.microsoft.com/Sql/2008/05/Notification/", Order=2)]
    public string Type;

    public Notification() {
    }

    public Notification(string Info, string Source, string Type) {
        this.Info = Info;
        this.Source = Source;
        this.Type = Type;
    }
}

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 notificación 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 : NotificationOperation {

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

Recepción de notificaciones de consulta mediante el modelo de servicio WCF

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

Para recibir notificaciones de consulta

  1. Use el complemento Add Adapter Service Reference (Agregar referencia del servicio adaptador) para generar un cliente WCF para la operación Select en la tabla Employee (Empleado ). Usará este cliente para realizar operaciones Select después de recibir un mensaje de notificación. Agregue una nueva clase, TableOperation.cs al proyecto y agregue el siguiente fragmento de código para realizar una operación Select.

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    
    namespace Notification_ServiceModel
    {
        public class TableOperation
        {
            public void TableOp()
            {
                ///////////////////////////////////////////////////////////////////////
                // CREATING THE CLIENT
                ///////////////////////////////////////////////////////////////////////
    
                TableOp_dbo_EmployeeClient client = new TableOp_dbo_EmployeeClient("SqlAdapterBinding_TableOp_dbo_Employee");
    
                client.ClientCredentials.UserName.UserName = "<Enter user name here>";
                client.ClientCredentials.UserName.Password = "<Enter password here>";
    
                ///////////////////////////////////////////////////////////////////////
                // OPENING THE CLIENT
                ///////////////////////////////////////////////////////////////////////
    
                try
                {
                    Console.WriteLine("Opening Client...");
                    client.Open();
                }
                catch (Exception ex)
                {
                    Console.WriteLine("Exception: " + ex.Message);
                    throw;
                }
    
                ///////////////////////////////////////////////////////////////////////
                // SELECTING THE LAST INSERTED RECORD FROM THE TABLE
                ///////////////////////////////////////////////////////////////////////
                schemas.microsoft.com.Sql._2008._05.Types.Tables.dbo.Employee[] selectRecords;
    
                try
                {
                    selectRecords = client.Select("*", "where Status=0");
                }
    
                catch (Exception ex)
                {
                    Console.WriteLine("Exception: " + ex.Message);
                    throw;
                }
    
                Console.WriteLine("The details of the newly added employee are:");
                Console.WriteLine("********************************************");
                for (int i = 0; i < selectRecords.Length; i++)
                {
                    Console.WriteLine("Employee Name      : " + selectRecords[i].Name);
                    Console.WriteLine("Employee Designation: " + selectRecords[i].Designation);
                    Console.WriteLine("Employee Status    : " + selectRecords[i].Status);
                    Console.WriteLine();
                }
                Console.WriteLine("********************************************");
    
    

    Importante

    Dado que este fragmento de código realiza operaciones en la tabla Employee que contiene una columna UDT point, asegúrese de colocar el archivo DLL udT en la carpeta \bin\Debug del proyecto mientras ejecuta la aplicación.

  2. Use el complemento Agregar referencia del servicio adaptador para generar un contrato de servicio WCF (interfaz) y clases auxiliares para la operación de notificación .

    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.

  3. Implemente un servicio WCF desde la interfaz y las clases auxiliares generadas en el paso 2. El método Notification de esta clase puede producir una excepción para anular la operación, si se produce un error al procesar los datos recibidos de la operación notificación ; 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 Notification , 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 notificación recibido se escribe en la consola. Además, se invoca el método TableOp dentro de la clase TableOperation para realizar la operación Select.

    [ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]
    
    public class NotificationService : SqlAdapterBindingNamespace.SqlAdapterBindingService
    {
        public override void Notification(Notification request)
        {
            Console.WriteLine("\nNew Notification Received");
            Console.WriteLine("*************************************************");
            Console.WriteLine(request.Info);
            Console.WriteLine(request.Source);
            Console.WriteLine(request.Type);
            Console.WriteLine("*************************************************");
    
            // Invoke th TableOp method in the TableOperation class
            TableOperation Ops = new TableOperation();
            Ops.TableOp();
        }
    }
    
  4. 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 NotificationCredentials : 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 NotificationCredentials();
            clone.UserName.UserName = this.UserName.UserName;
            clone.UserName.Password = this.UserName.Password;
            return clone;
        }
    }
    
  5. Cree sqlAdapterBinding y configure el adaptador para recibir notificaciones de consulta 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 las propiedades de enlace InboundOperationType y NotificationStatement .

    SqlAdapterBinding binding = new SqlAdapterBinding();
    binding.InboundOperationType = InboundOperation.Notification;
    binding.NotificationStatement = "SELECT Employee_ID, Name FROM dbo.Employee WHERE Status=0";
    binding.NotifyOnListenerStart = true;
    
  6. Especifique SQL Server credenciales de base de datos creando instancias de la clase NotificationCredentials que creó en el paso 4.

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

    // create service instance
    NotificationService service = new NotificationService();
    
  8. Cree una instancia de System.ServiceModel.ServiceHost mediante el servicio WCF y un URI de conexión base. 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);
    
    
  9. Agregue un punto de conexión de servicio al host de servicio. Para ello, siga estos pasos:

    • Use el enlace creado en el paso 5.

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

    • Especifique el contrato como "NotificationOperation".

      // Add service endpoint: be sure to specify NotificationOperation as the contract
      Uri ConnectionUri = new Uri("mssql://mysqlserver//mydatabase?");
      serviceHost.AddServiceEndpoint("NotificationOperation", binding, ConnectionUri);
      
  10. Para recibir el mensaje de notificación, abra el host de servicio.

    // Open the service host to begin receiving notifications
    serviceHost.Open();
    
  11. Para dejar de recibir notificaciones, cierre el host del servicio.

    serviceHost.Close();
    

Ejemplo

En el ejemplo siguiente se muestra una aplicación .NET para recibir mensajes de notificación para la tabla Employee.

Nota

El siguiente fragmento de código crea una instancia de una clase TableOperation.cs e invoca el método TableOp . La clase y el método se describen en el paso 1.

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 Notification_ServiceModel
{
    [ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]
    public class NotificationService : SqlAdapterBindingNamespace.SqlAdapterBindingService
    {
        public override void Notification(Notification request)
        {
            Console.WriteLine("\nNew Notification Received");
            Console.WriteLine("*************************************************");
            Console.WriteLine(request.Info);
            Console.WriteLine(request.Source);
            Console.WriteLine(request.Type);
            Console.WriteLine("*************************************************");
            TableOperation Ops = new TableOperation();
            Ops.TableOp();
        }
    }

    class NotificationCredentials : 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 NotificationCredentials();
            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
            {
                SqlAdapterBinding binding = new SqlAdapterBinding();
                binding.InboundOperationType = InboundOperation.Notification;
                binding.NotificationStatement = "SELECT Employee_ID, Name FROM dbo.Employee WHERE Status=0";
                binding.NotifyOnListenerStart = true;

                // 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") };

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

                Console.WriteLine("Opening service host...");
                NotificationService service = new NotificationService();
                serviceHost = new ServiceHost(service, baseUri);
                serviceHost.Description.Behaviors.Add(credentials);
                serviceHost.AddServiceEndpoint("NotificationOperation", binding, ConnectionUri);
                serviceHost.Open();
                Console.WriteLine("Service host opened...");
                Console.WriteLine("Waiting for notification...");

                Console.WriteLine("\nHit <RETURN> to stop receiving notification");
                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 receiving notifications
                if (serviceHost.State == CommunicationState.Opened)
                    serviceHost.Close();
                else
                    serviceHost.Abort();
            }
        }
    }
}

Consulte también

Desarrollo de aplicaciones SQL mediante el modelo de servicio WCF