Freigeben über


Empfangen von Oracle-Datenbankänderungsbenachrichtigungen mithilfe des WCF-Dienstmodells1

In diesem Thema wird veranschaulicht, wie Sie den Oracle Database-Adapter konfigurieren, um Abfragebenachrichtigungsmeldungen aus einer Oracle-Datenbank zu empfangen. Um Benachrichtigungen zu veranschaulichen, betrachten Sie die Tabelle ACCOUNTACTIVITY mit der Spalte "Verarbeitet". Wenn ein neuer Datensatz in diese Tabelle eingefügt wird, wird der Wert der Spalte Status auf "n" festgelegt. Sie können den Adapter für den Empfang von Benachrichtigungen konfigurieren, indem Sie eine SQL-Anweisung verwenden, die alle Datensätze mit der Spalte "Verarbeitet" als "n" abruft. Dazu geben Sie die SQL-Anweisung für die NotificationStatement-Bindungseigenschaft an. Sobald der Adapterclient die Benachrichtigung empfangen hat, kann er die Logik enthalten, um alle nachfolgenden Aufgaben in der Oracle-Datenbank auszuführen. In diesem Beispiel listet der Adapterclient der Einfachheit halber alle Datensätze in der Tabelle auf, die die Spalte "Verarbeitet" als "n" aufweisen.

Konfigurieren von Benachrichtigungen mit den Bindungseigenschaften des Oracle-Datenbankadapters

In der folgenden Tabelle sind die Bindungseigenschaften des Oracle Database-Adapters zusammengefasst, die Sie zum Konfigurieren des Empfangens von Benachrichtigungen aus der Oracle-Datenbank verwenden. Sie müssen diese Bindungseigenschaften beim Ausführen der .NET-Anwendung angeben, um Benachrichtigungen zu empfangen.

Bindungseigenschaft BESCHREIBUNG
InboundOperationType Gibt den eingehenden Vorgang an, den Sie ausführen möchten. Legen Sie zum Empfangen von Benachrichtigungen dies auf Benachrichtigung fest.
NotificationPort Gibt die Portnummer an, die ODP.NET öffnen muss, um auf Datenbankänderungsbenachrichtigungen aus der Oracle-Datenbank zu lauschen.
NotificationStatement Gibt die SELECT-Anweisung an, die zum Registrieren von Abfragebenachrichtigungen verwendet wird. Der Adapter erhält nur dann eine Benachrichtigung, wenn sich das Resultset für die angegebene SELECT-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 Konfigurieren der Bindungseigenschaften für Oracle Database. Eine vollständige Beschreibung der Verwendung des Oracle Database-Adapters zum Empfangen von Benachrichtigungen aus der Oracle-Datenbank finden Sie weiter.

Konfigurieren von Benachrichtigungen mithilfe des WCF-Dienstmodells

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

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

  • Generieren Sie einen WCF-Client für den Select-Vorgang in der Tabelle ACCOUNTACTIVITY. Dazu können Sie das Add Adapter Service Reference Plug-In verwenden.

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

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

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 eines WCF-Dienstvertrags für Oracle Database-Lösungsartefakte.

Wcf-Dienstvertrag (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://Microsoft.LobServices.OracleDB/2007/03", ConfigurationName="Notification_OperationGroup")]
public interface Notification_OperationGroup {

    // CODEGEN: Generating message contract since the wrapper namespace (http://Microsoft.LobServices.OracleDB/2007/03/Notification/) of message Notification
    // does not match the default value (http://Microsoft.LobServices.OracleDB/2007/03)
    [System.ServiceModel.OperationContractAttribute(IsOneWay=true, Action="http://Microsoft.LobServices.OracleDB/2007/03/Notification")]
    void Notification(Notification request);
}

Nachrichtenverträge

Im Folgenden ist der Nachrichtenvertrag für den Benachrichtigungsvorgang aufgeführt.

[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "3.0.0.0")]
[System.ServiceModel.MessageContractAttribute(WrapperName="Notification", WrapperNamespace="http://Microsoft.LobServices.OracleDB/2007/03/Notification/", IsWrapped=true)]
public partial class Notification {

    [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://Microsoft.LobServices.OracleDB/2007/03/Notification/", Order=0)]
    public microsoft.lobservices.oracledb._2007._03.Notification.NotificationDetails[] Details;

    [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://Microsoft.LobServices.OracleDB/2007/03/Notification/", Order=1)]
    public string Info;

    [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://Microsoft.LobServices.OracleDB/2007/03/Notification/", Order=2)]
    public string[] ResourceNames;

    [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://Microsoft.LobServices.OracleDB/2007/03/Notification/", Order=3)]
    public string Source;

    [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://Microsoft.LobServices.OracleDB/2007/03/Notification/", Order=4)]
    public string Type;

    public Notification() {
    }

    public Notification(microsoft.lobservices.oracledb._2007._03.Notification.NotificationDetails[] Details, string Info, string[] ResourceNames, string Source, string Type) {
        this.Details = Details;
        this.Info = Info;
        this.ResourceNames = ResourceNames;
        this.Source = Source;
        this.Type = Type;
    }
}

WCF-Dienstklasse

Das Add Adapter Service Reference Plug-In generiert auch eine Datei, die einen Stub für die WCF-Dienstklasse aus dem Dienstvertrag (Schnittstelle) implementiert hat. Der Name der Datei lautet OracleDBBindingService.cs. Sie können die Logik zum Verarbeiten des Benachrichtigungsvorgangs direkt in diese Klasse einfügen. Der folgende Code zeigt die WCF-Dienstklasse, die vom Add Adapter Service Reference Plug-In generiert wurde.

namespace OracleDBBindingNamespace {

    public class OracleDBBindingService : Notification_OperationGroup {

        // CODEGEN: Generating message contract since the wrapper namespace (http://Microsoft.LobServices.OracleDB/2007/03/Notification/) of message Notification
        // does not match the default value (http://Microsoft.LobServices.OracleDB/2007/03)
        public virtual void Notification(Notification request) {
            throw new System.NotImplementedException("The method or operation is not implemented.");
        }
    }
}

Empfangen von Datenbankänderungsbenachrichtigungen mithilfe des WCF-Dienstmodells

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

So empfangen Sie Abfragebenachrichtigungen

  1. Verwenden Sie das Add Adapter Service Reference Plug-In , um einen WCF-Client für den Select-Vorgang in der Tabelle ACCOUNTACTIVITY zu generieren. Sie verwenden diesen Client, um Select-Vorgänge auszuführen, nachdem sie eine Benachrichtigung erhalten haben. Fügen Sie Ihrem Projekt die 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
    {
        class TableOperation
        {
            public void TableOp()
            {
                //////////////////////////////////////////////////////////////////////
                // CREATING THE CLIENT AND SETTING CLIENT CREDENTIALS
                //////////////////////////////////////////////////////////////////////
    
                SCOTT_Table_ACCOUNTACTIVITYClient client = new SCOTT_Table_ACCOUNTACTIVITYClient("OracleDBBinding_SCOTT_Table_ACCOUNTACTIVITY");
                client.ClientCredentials.UserName.UserName = "SCOTT";
                client.ClientCredentials.UserName.Password = "TIGER";
    
                ////////////////////////////////////////////////////////////////////
                // OPENING THE CLIENT
                //////////////////////////////////////////////////////////////////////
                try
                {
                    Console.WriteLine("Opening the client ...");
                    client.Open();
                }
                catch (Exception ex)
                {
                    Console.WriteLine("Exception: " + ex.Message);
                    throw;
                }
    
                ////////////////////////////////////////////////////////////////////////////////////////
                // SELECTING THE LAST INSERTED VALUE
                ////////////////////////////////////////////////////////////////////////////////////////
    
                Console.WriteLine("The application will now select the last inserted record");
    
                microsoft.lobservices.oracledb._2007._03.SCOTT.Table.ACCOUNTACTIVITY.ACCOUNTACTIVITYRECORDSELECT[] selectRecords;
    
                try
                {
                    selectRecords = client.Select("*", "WHERE PROCESSED = 'n'");
                }
                catch (Exception ex)
                {
                    Console.WriteLine("Exception: " + ex.Message);
                    throw;
                }
    
                Console.WriteLine("The details of the newly added records are:");
                Console.WriteLine("********************************************");
                for (int i = 0; i < selectRecords.Length; i++)
                {
                    Console.WriteLine("Transaction ID   : " + selectRecords[i].TID);
                    Console.WriteLine("Account ID       : " + selectRecords[i].ACCOUNT);
                    Console.WriteLine("Processed Status : " + selectRecords[i].PROCESSED);
                    Console.WriteLine();
                }
                Console.WriteLine("********************************************");
            }
        }
    }
    
    
  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-Clients oder eines WCF-Dienstvertrags für Oracle Database-Lösungsartefakte. 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 werden.

  3. Implementieren Sie einen WCF-Dienst aus der In Schritt 2 generierten Schnittstellen- und Hilfsklassen. Die Notification-Methode dieser Klasse kann eine Ausnahme auslösen, um den Vorgang abzubrechen, wenn ein Fehler bei der Verarbeitung der vom Benachrichtigungsvorgang empfangenen Daten auftritt. andernfalls gibt die Methode nichts zurück. Sie müssen die WCF-Dienstklasse wie folgt zuordnen:

    [ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]
    

    Innerhalb der Benachrichtigungsmethode können Sie Ihre Anwendungslogik direkt implementieren. Diese Klasse finden Sie in OracleDBBindingService.cs. Dieser Code in diesem Beispiel unterordnet die OracleDBBindingService-Klasse . In diesem Code wird die empfangene Benachrichtigungsnachricht 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 : OracleDBBindingNamespace.OracleDBBindingService
        {
            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();
    
            }
        }
    
  4. Sie müssen die folgende Klasse implementieren, um Anmeldeinformationen für die Oracle-Datenbank zu übergeben. Im letzten Teil der Anwendung instanziieren Sie diese Klasse, um die 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 eine OracleDBBinding-Instanz , und konfigurieren Sie den Adapter für den Empfang von Abfragebenachrichtigungen, indem Sie die Bindungseigenschaften angeben. Sie können dies entweder explizit im Code oder deklarativ in der Konfiguration tun. Mindestens müssen Sie die Bindungseigenschaften InboundOperationType und NotificationStatement angeben.

    OracleDBBinding binding = new OracleDBBinding();
    binding.InboundOperationType = InboundOperation.Notification;
    binding.NotificationStatement = "SELECT TID,ACCOUNT,PROCESSED FROM APPS.ACCOUNTACTIVITY WHERE PROCESSED = 'n'";
    binding.NotifyOnListenerStart = true;
    binding.NotificationPort = 10;
    

    Wichtig

    Der Wert für die NotificationPort-Bindungseigenschaft muss auf dieselbe Portnummer festgelegt werden, die Sie der Liste der Windows-Firewall-Ausnahmen hinzugefügt haben müssen. Anweisungen zum Hinzufügen von Ports zur Liste der Windows-Firewallausnahmen finden Sie unter https://go.microsoft.com/fwlink/?LinkId=196959.

    Wichtig

    Wenn Sie die NotificationPort-Bindungseigenschaft nicht festlegen, nimmt der Adapter den Standardwert -1 für diese Bindungseigenschaft an. In einem solchen Fall müssen Sie die Windows-Firewall vollständig deaktivieren, um Benachrichtigungen zu empfangen.

  6. Geben Sie Die Anmeldeinformationen der Oracle-Datenbank an, indem Sie die NotificationCredentials-Klasse instanziieren, die Sie in Schritt 4 erstellt haben.

    NotificationCredentials credentials = new NotificationCredentials();
    credentials.UserName.UserName = "SCOTT";
    credentials.UserName.Password = "TIGER";
    
  7. Erstellen Sie eine instance des WCF-Diensts, der in Schritt 3 erstellt wurde.

    // create service instance
    NotificationService service = new NotificationService();
    
  8. Erstellen Sie eine instance 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("oracledb://adapter") };
    ServiceHost serviceHost = new ServiceHost(service, baseUri);
    serviceHost.Description.Behaviors.Add(credentials);
    
    
  9. Fügen Sie dem Diensthost einen Dienstendpunkt hinzu. Gehen Sie dazu folgendermaßen vor:

    • Verwenden Sie die in Schritt 5 erstellte Bindung.

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

    • Geben Sie den Vertrag als "Notification_OperationGroup" an.

      // Add service endpoint: be sure to specify Notification_OperationGroup as the contract
      Uri ConnectionUri = new Uri("oracledb://adapter");
      serviceHost.AddServiceEndpoint("Notification_OperationGroup", 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 ACCOUNTACTIVITY.

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.OracleDB;
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 : OracleDBBindingNamespace.OracleDBBindingService
    {
        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
            {
                Console.WriteLine("Sample started...");
                Console.WriteLine("Press any key to start receiving notifications...");
                Console.ReadLine();

                OracleDBBinding binding = new OracleDBBinding();
                binding.InboundOperationType = InboundOperation.Notification;
                binding.NotificationStatement = "SELECT TID,ACCOUNT,PROCESSED FROM APPS.ACCOUNTACTIVITY WHERE PROCESSED = 'n'";
                binding.NotifyOnListenerStart = true;
                binding.NotificationPort = 10;

                // 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("oracledb://adapter");

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

                NotificationCredentials credentials = new NotificationCredentials();
                credentials.UserName.UserName = "SCOTT";
                credentials.UserName.Password = "TIGER";

                Console.WriteLine("Opening service host...");
                NotificationService service = new NotificationService();
                serviceHost = new ServiceHost(service, baseUri);
                serviceHost.Description.Behaviors.Add(credentials);
                serviceHost.AddServiceEndpoint("Notification_OperationGroup", 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 polling
                if (serviceHost.State == CommunicationState.Opened)
                    serviceHost.Close();
                else
                    serviceHost.Abort();
            }

        }
    }
}

Weitere Informationen

Entwickeln von Oracle Database-Anwendungen mithilfe des WCF-Dienstmodells