Empfangen von Abfragebenachrichtigungen aus SQL mithilfe des WCF-Dienstmodells

In diesem Thema wird veranschaulicht, wie Sie den SQL-Adapter so konfigurieren, dass Abfragebenachrichtigungen aus einer SQL Server-Datenbank empfangen werden. Um Benachrichtigungen zu veranschaulichen, betrachten Sie eine Tabelle, "Mitarbeiter" mit einer Spalte "Status". Wenn ein neuer Datensatz in diese Tabelle eingefügt wird, wird der Wert der Spalte Status auf 0 festgelegt. Sie können den Adapter so konfigurieren, dass er Benachrichtigungen empfängt, indem Sie sich für Benachrichtigungen registrieren, indem Sie eine SQL-Anweisung verwenden, die alle Datensätze abruft, die die Spalte "Status" als "0" aufweisen. Dazu können Sie die SQL-Anweisung für die NotificationStatement-Bindungseigenschaft angeben. Nachdem der Adapterclient die Benachrichtigung erhält, kann er die Logik enthalten, um alle nachfolgenden Aufgaben in der SQL Server-Datenbank auszuführen. In diesem Beispiel listet der Adapterclient aus Gründen der Einfachheit alle Datensätze in der Tabelle auf, die die Statusspalte als "0" aufweisen.

Hinweis

Wenn Sie Vorgänge für Tabellen mit Spalten benutzerdefinierter Typen ausführen, stellen Sie sicher, dass Sie auf Vorgänge in Tabellen und Ansichten mit benutzerdefinierten Typen mithilfe des THEMAs "SQL-Adapter " verweisen, bevor Sie mit der Entwicklung der Anwendung beginnen.

Konfigurieren von Benachrichtigungen mit den SQL-Adapterbindungseigenschaften

In der folgenden Tabelle sind die SQL-Adapterbindungseigenschaften zusammengefasst, die Sie zum Konfigurieren des Empfangens von Benachrichtigungen von SQL Server verwenden. Sie müssen diese Bindungseigenschaften angeben, während die .NET-Anwendung ausgeführt wird, um die Benachrichtigungen aus einer SQL Server-Datenbank zu empfangen.

Binding-Eigenschaft BESCHREIBUNG
InboundOperationType Gibt den ankommenden Vorgang an, den Sie ausführen möchten. Um Benachrichtigungen zu empfangen, legen Sie dies auf "Benachrichtigung" fest.
NotificationStatement Gibt die SQL-Anweisung (SELECT oder EXEC <gespeicherte Prozedur>) an, die zum Registrieren für Abfragebenachrichtigungen verwendet wird. Der Adapter erhält eine Benachrichtigung von SQL Server nur, wenn sich die Ergebnismenge für die angegebene SQL-Anweisung ändert.
NotifyOnListenerStart Gibt an, ob der Adapter beim Starten des Listeners eine Benachrichtigung an die Adapterclients sendet.

Eine ausführlichere Beschreibung dieser Eigenschaften finden Sie unter BizTalk Adapter für SQL Server-Adapterbindungseigenschaften. Eine vollständige Beschreibung der Verwendung des SQL-Adapters zum Empfangen von Benachrichtigungen von SQL Server finden Sie weiter.

Konfigurieren von Benachrichtigungen mithilfe des WCF-Dienstmodells

Um die Benachrichtigungen mithilfe des WCF-Dienstmodells zu erhalten, müssen Sie:

  1. Generieren Sie einen WCF-Dienstvertrag (Schnittstelle) für den Benachrichtigungsvorgang aus den vom Adapter verfügbar gemachten Metadaten. Dazu können Sie das Add Adapter Service Reference Plug-In verwenden.

  2. Generieren Sie einen WCF-Client für den Auswahlvorgang in der Tabelle "Mitarbeiter". Dazu können Sie das Add Adapter Service Reference Plug-In verwenden.

  3. Implementieren Sie einen WCF-Dienst über diese Schnittstelle.

  4. Hosten Sie diesen WCF-Dienst mithilfe eines Diensthosts (System.ServiceModel.ServiceHost).

Informationen zu den in diesem Thema verwendeten Beispielen

Die Beispiele in diesem Thema erhalten Benachrichtigungen für die Tabelle "Mitarbeiter". Ein Skript zum Generieren der Tabelle wird mit den Beispielen bereitgestellt. Weitere Informationen zu den Beispielen finden Sie unter Beispiele für den SQL-Adapter. Ein Beispiel, Notification_ServiceModel, das auf diesem Thema basiert, wird auch mit den SQL-Adapterbeispielen bereitgestellt.

WCF-Dienstvertrag und -Klasse

Sie können das Add Adapter Service Reference Plug-In verwenden, um einen WCF-Dienstvertrag (Schnittstelle) und unterstützende Klassen für den Benachrichtigungsvorgang zu erstellen. Weitere Informationen zum Generieren eines WCF-Dienstvertrags finden Sie unter Generieren eines WCF-Clients oder WCF-Dienstvertrags für SQL Server Artifacts.

Der WCF-Servicekontrakt (Schnittstelle)

Der folgende Code zeigt den WCF-Dienstvertrag (Schnittstelle), der für den Benachrichtigungsvorgang generiert wurde.

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

Die Nachrichtenverträge

Nachfolgend sehen Sie den Nachrichtenvertrag für den Benachrichtigungsvorgang.

[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;
    }
}

WCF-Dienstklasse

Das Add-Adapter Service Reference Plug-In generiert auch eine Datei, die über einen Stub für die WCF-Dienstklasse verfügt, die aus dem Dienstvertrag (Schnittstelle) implementiert wurde. Der Name der Datei ist SqlAdapterBindingService.cs. Sie können die Logik einfügen, um den Benachrichtigungsvorgang direkt in diese Klasse zu verarbeiten. Der folgende Code zeigt die WCF-Dienstklasse, die vom Add Adapter Service Reference Plug-In generiert wird.

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

Empfangen von Abfragebenachrichtigungen mithilfe des WCF-Dienstmodells

Dieser Abschnitt enthält Anweisungen zum Schreiben einer .NET-Anwendung zum Empfangen von Abfragebenachrichtigungen mithilfe des SQL-Adapters.

So empfangen Sie Abfragebenachrichtigungen

  1. Verwenden Sie das Add Adapter Service Reference Plug-In, um einen WCF-Client für den Auswahlvorgang in der Tabelle "Mitarbeiter " zu generieren. Sie verwenden diesen Client, um Select-Vorgänge auszuführen, nachdem sie eine Benachrichtigung erhalten haben. Fügen Sie ihrem Projekt eine neue Klasse TableOperation.cs hinzu, und fügen Sie den folgenden Codeausschnitt hinzu, um einen Select-Vorgang auszuführen.

    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("********************************************");
    
    

    Von Bedeutung

    Da dieser Codeausschnitt Vorgänge in der Tabelle "Mitarbeiter" ausführt, die eine Spalte "Point UDT" enthält, stellen Sie sicher, dass Sie die UDT-DLL unter dem Ordner "\bin\Debug" des Projekts ablegen, während sie die Anwendung ausführen.

  2. Verwenden Sie das Add Adapter Service Reference Plug-In, um einen WCF-Dienstvertrag (Schnittstelle) und Hilfsklassen für den Benachrichtigungsvorgang zu generieren.

    Weitere Informationen finden Sie unter Generieren eines WCF-Client- oder WCF-Dienstvertrags für SQL Server-Artefakte. Optional können Sie die Bindungseigenschaften beim Generieren des Dienstvertrags und der Hilfsklassen angeben. Dadurch wird sichergestellt, dass sie in der generierten Konfigurationsdatei ordnungsgemäß festgelegt sind.

  3. Implementieren Sie einen WCF-Dienst über die Schnittstelle und Hilfsklassen, die in Schritt 2 generiert wurden. Die Notification-Methode dieser Klasse kann eine Ausnahme auslösen, um den Vorgang abzubrechen, wenn beim Verarbeiten der vom Benachrichtigungsvorgang empfangenen Daten ein Fehler aufgetreten ist; andernfalls gibt die Methode nichts zurück. Sie müssen die WCF-Dienstklasse wie folgt attributen:

    [ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]
    

    Innerhalb der Notification-Methode können Sie Ihre Anwendungslogik direkt implementieren. Diese Klasse finden Sie in SqlAdapterBindingService.cs. In diesem Beispiel erweitert der Code die SqlAdapterBindingService-Klasse. In diesem Code wird die empfangene Benachrichtigung in die Konsole geschrieben. Darüber hinaus wird die TableOp-Methode innerhalb der TableOperation-Klasse aufgerufen, um den Select-Vorgang auszuführen.

    [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. Da der SQL-Adapter Anmeldeinformationen nicht als Teil des Verbindungs-URI akzeptiert, müssen Sie die folgende Klasse implementieren, um Anmeldeinformationen für die SQL Server-Datenbank zu übergeben. Im letzten Teil der Anwendung instanziieren Sie diese Klasse, um die SQL Server-Anmeldeinformationen zu übergeben.

    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. Erstellen Sie ein SqlAdapterBinding und konfigurieren Sie den Adapter so, dass er Abfragebenachrichtigungen empfängt, indem Sie die Bindungseigenschaften angeben. Sie können dies entweder explizit im Code oder deklarativ in der Konfiguration tun. Sie müssen mindestens die Bindungseigenschaften "InboundOperationType " und "NotificationStatement " angeben.

    SqlAdapterBinding binding = new SqlAdapterBinding();
    binding.InboundOperationType = InboundOperation.Notification;
    binding.NotificationStatement = "SELECT Employee_ID, Name FROM dbo.Employee WHERE Status=0";
    binding.NotifyOnListenerStart = true;
    
  6. Geben Sie SQL Server-Datenbankanmeldeinformationen an, indem Sie die notificationCredentials-Klasse instanziieren, die Sie in Schritt 4 erstellt haben.

    NotificationCredentials credentials = new NotificationCredentials();
    credentials.UserName.UserName = "<Enter user name here>";
    credentials.UserName.Password = "<Enter password here>";
    
  7. Erstellen Sie eine Instanz des WCF-Diensts, der in Schritt 3 erstellt wurde.

    // create service instance
    NotificationService service = new NotificationService();
    
  8. Erstellen Sie eine Instanz von System.ServiceModel.ServiceHost mithilfe des WCF-Diensts und eines Basisverbindungs-URI. Sie müssen hier auch die Anmeldeinformationen angeben.

    // Enable service host
    Uri[] baseUri = new Uri[] { new Uri("mssql://mysqlserver//mydatabase") };
    ServiceHost serviceHost = new ServiceHost(service, baseUri);
    serviceHost.Description.Behaviors.Add(credentials);
    
    
  9. Fügen Sie dem Diensthost einen Dienstendpunkt hinzu. Um dies zu tun:

    • Verwenden Sie die in Schritt 5 erstellte Bindung.

    • Geben Sie einen Verbindungs-URI an, der Anmeldeinformationen und ggf. eine Eingangs-ID enthält.

    • Geben Sie den Vertrag als "NotificationOperation" an.

      // Add service endpoint: be sure to specify NotificationOperation as the contract
      Uri ConnectionUri = new Uri("mssql://mysqlserver//mydatabase?");
      serviceHost.AddServiceEndpoint("NotificationOperation", binding, ConnectionUri);
      
  10. Um eine Benachrichtigung zu erhalten, öffnen Sie den Diensthost.

    // Open the service host to begin receiving notifications
    serviceHost.Open();
    
  11. Um den Empfang von Benachrichtigungen zu beenden, schließen Sie den Diensthost.

    serviceHost.Close();
    

Beispiel

Das folgende Beispiel zeigt eine .NET-Anwendung zum Empfangen von Benachrichtigungen für die Tabelle "Mitarbeiter".

Hinweis

Der folgende Codeausschnitt instanziiert eine TableOperation.cs Klasse und ruft die TableOp-Methode auf. Die Klasse und die Methode werden in Schritt 1 beschrieben.

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

Siehe auch

Entwickeln von SQL-Anwendungen mithilfe des WCF-Dienstmodells