Empfangen von abfragenbasierten datenveränderten Nachrichten in Oracle Database mithilfe des WCF-Dienstmodells
Sie können den Microsoft BizTalk-Adapter für Oracle-Datenbank so konfigurieren, dass auf Abruf basierende Daten geänderte Nachrichten für eine Oracle-Tabelle oder -Sicht empfangen werden. Um datenveränderte Nachrichten zu empfangen, führt der Adapter in regelmäßigen Abständen eine SQL-Abfrage für eine Oracle-Tabelle oder -Sicht aus, gefolgt von einem optionalen PL/SQL-Codeblock. Die Ergebnisse der SQL-Abfrage werden dann vom Oracle Database-Adapter als stark typisiertes Resultset in einem eingehenden POLLINGSTMT-Vorgang an Ihre Anwendung zurückgegeben. Weitere Informationen zum Mechanismus zum Konfigurieren und Durchführen von Abfragen in einer Oracle-Datenbank mithilfe des Oracle Database-Adapters finden Sie unter Empfangen von abrufbasierten datenveränderten Nachrichten im Oracle Database-Adapter. Es wird dringend empfohlen, dieses Thema zu lesen, bevor Sie fortfahren.
Um den POLLINGSTMT-Vorgang zu erhalten, wenn Sie das WCF-Dienstmodell verwenden, müssen Sie:
Generieren Sie einen WCF-Dienstvertrag (Schnittstelle) für den POLLINGSTMT-Vorgang aus den Metadaten, die vom Adapter verfügbar gemacht werden. Dazu verwenden Sie das Visual Studio-Plug-In Adapter Service Reference hinzufügen oder das ServiceModel Metadata Utility Tool (svcutil.exe).
Implementieren Sie über diese Schnittstelle einen WCF-Dienst.
Hosten Sie diesen WCF-Dienst mithilfe eines Diensthosts (System.ServiceModel.ServiceHost).
Die Themen in diesem Abschnitt enthalten Informationen und Verfahren, mit denen Sie Abfragen für Oracle-Datenbanktabellen und -ansichten im WCF-Dienstmodell durchführen können.
Informationen zu den in diesem Thema verwendeten Beispielen
Die Beispiele in diesem Thema verwenden die Tabelle /SCOTT/ACCOUNTACTIVITY und die Funktion /SCOTT/Package/ACCOUNT_PKG/PROCESS_ACTIVITY. Ein Skript zum Generieren dieser Artefakte wird mit den BizTalk Adapter Pack-Beispielen bereitgestellt. Weitere Informationen zu den Beispielen finden Sie unter Adapterbeispiele.
Konfigurieren der Abfrage im WCF-Dienstmodell
Sie konfigurieren den Oracle Database-Adapter für die Durchführung von Abfragen für Oracle-Datenbanktabellen und -ansichten, indem Sie Bindungseigenschaften und eine optionale Verbindungseigenschaft (Parameter) festlegen. Einige dieser Eigenschaften sind obligatorisch, und einige, um eine Wirkung zu erzielen, müssen sowohl zur Entwurfszeit als auch zur Laufzeit festgelegt werden.
Zur Entwurfszeit legen Sie Verbindungsparameter und Bindungseigenschaften fest, wenn Sie eine Verbindung mit der Oracle-Datenbank herstellen, um einen WCF-Dienstvertrag zu generieren.
Zur Laufzeit legen Sie Bindungseigenschaften für das OracleDBBinding-Objekt fest, das Sie zum Erstellen des Diensthosts verwenden. Sie legen den Verbindungsparameter fest, wenn Sie dem Diensthost einen Dienstlistener hinzufügen.
Die folgende Liste bietet einen kurzen Überblick über die Bindungseigenschaften und Verbindungsparameter, die zum Konfigurieren der Abrufe verwendet werden:
Die PollingStatement-Bindungseigenschaft . Sie müssen diese Bindungseigenschaft sowohl zur Entwurfszeit als auch zur Laufzeit festlegen.
Optionale Bindungseigenschaften. Diese müssen nur zur Laufzeit festgelegt werden.
Die AcceptCredentialsInUri-Bindungseigenschaft . Sie müssen diese Bindungseigenschaft während der Laufzeit auf true festlegen, wenn Sie Anmeldeinformationen im Verbindungs-URI aktivieren möchten. Der Benutzername und das Kennwort müssen im Verbindungs-URI vorhanden sein, wenn Sie dem Diensthost einen Dienstendpunkt hinzufügen.
Der Abfragezeichenfolgenparameter PollingId im Verbindungs-URI. Wenn Sie den Namespace des POLLINGSTMT-Vorgangs ändern möchten, müssen Sie diese Verbindungseigenschaft sowohl zur Entwurfs- als auch zur Laufzeit festlegen.
Eine vollständige Beschreibung der Bindungseigenschaften und Verbindungsparameter, die zum Konfigurieren der Abfrage verwendet werden, finden Sie unter Empfangen von abrufbasierten datenveränderten Nachrichten im Oracle Database-Adapter.
Wcf-Dienstvertrag und -Klasse
Sie verwenden entweder das Visual Studio-Plug-In Add Adapter Service Reference oder das ServiceModel Metadata Utility Tool (svcutil.exe), um einen WCF-Dienstvertrag (Schnittstelle) und unterstützende Klassen für den POLLINGSTMT-Vorgang zu erstellen.
Wenn Sie mit einem der folgenden Tools eine Verbindung mit der Oracle-Datenbank herstellen, um einen Dienstvertrag für den POLLINGSTMT-Vorgang zu generieren:
Sie müssen die Eigenschaft PollingStatement-Bindung angeben. Der Adapter verwendet die SELECT-Anweisung in dieser Bindungseigenschaft, um die richtigen Metadaten für das stark typisierte Resultset zu generieren, das vom POLLINGSTMT-Vorgang zurückgegeben wird.
Optional können Sie einen PollingId-Parameter im Verbindungs-URI angeben. Der Adapter verwendet diesen Parameter, um den Namespace für den POLLINGSTMT-Vorgang zu generieren.
In den folgenden Beispielen:
PollingStatement ist auf "SELECT * FROM ACCOUNTACTIVITY FOR UPDATE" festgelegt.
PollingId ist auf "AcctActivity" festgelegt.
Wcf-Dienstvertrag (Schnittstelle)
Der folgende Code zeigt den WCF-Dienstvertrag (Schnittstelle), der für den POLLINGSTMT-Vorgang generiert wurde.
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "3.0.0.0")]
[System.ServiceModel.ServiceContractAttribute(Namespace="http://Microsoft.LobServices.OracleDB/2007/03", ConfigurationName="POLLINGSTMT_OperationGroup")]
public interface POLLINGSTMT_OperationGroup {
// CODEGEN: Generating message contract since the wrapper namespace (http://Microsoft.LobServices.OracleDB/2007/03/POLLINGSTMTAcctActivity)
// of message POLLINGSTMT does not match the default value (http://Microsoft.LobServices.OracleDB/2007/03)
[System.ServiceModel.OperationContractAttribute(IsOneWay=true, Action="http://Microsoft.LobServices.OracleDB/2007/03/POLLINGSTMT")]
void POLLINGSTMT(POLLINGSTMT request);
}
Nachrichtenverträge
Der Nachrichtenvertragsnamespace wird durch den PollingId-Parameter im Verbindungs-URI geändert. Die Anforderungsnachricht gibt einen Satz stark typisierter Datensätze zurück.
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "3.0.0.0")]
[System.ServiceModel.MessageContractAttribute(WrapperName="POLLINGSTMT", WrapperNamespace="http://Microsoft.LobServices.OracleDB/2007/03/POLLINGSTMTAcctActivity", IsWrapped=true)]
public partial class POLLINGSTMT {
[System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://Microsoft.LobServices.OracleDB/2007/03/POLLINGSTMTAcctActivity", Order=0)]
public microsoft.lobservices.oracledb._2007._03.POLLINGSTMTAcctActivity.POLLINGSTMTRECORD[] POLLINGSTMTRECORD;
public POLLINGSTMT() {
}
public POLLINGSTMT(microsoft.lobservices.oracledb._2007._03.POLLINGSTMTAcctActivity.POLLINGSTMTRECORD[] POLLINGSTMTRECORD) {
this.POLLINGSTMTRECORD = POLLINGSTMTRECORD;
}
}
Der Datenvertragsnamespace
Ein neuer Datenvertrag ist eine formale Vereinbarung zwischen einem Dienst und einem Client, in dem die auszutauschenden Daten abstrakt beschrieben werden. Das heißt, für die Kommunikation müssen client und Dienst nicht dieselben Typen, nur dieselben Datenverträge verwenden.
Bei Datenänderungsmeldungen wird der Datenvertragsnamespace auch durch den PollingId-Parameter (sofern angegeben) im Verbindungs-URI geändert. Der Datenvertrag besteht aus einer Klasse, die einen stark typisierten Datensatz im Abfrageergebnissatz darstellt. Die Details der Klassendefinition werden in diesem Beispiel nicht angegeben. Die -Klasse enthält Eigenschaften, die die Spalten im Resultset darstellen.
Im folgenden Beispiel wird die PollingId "AcctActivity" verwendet.
namespace microsoft.lobservices.oracledb._2007._03.POLLINGSTMTAcctActivity {
using System.Runtime.Serialization;
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.Runtime.Serialization", "3.0.0.0")]
[System.Runtime.Serialization.DataContractAttribute(Name="POLLINGSTMTRECORD", Namespace="http://Microsoft.LobServices.OracleDB/2007/03/POLLINGSTMTAcctActivity")]
public partial class POLLINGSTMTRECORD : object, System.Runtime.Serialization.IExtensibleDataObject {…}
}
}
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 POLLINGSTMT-Vorgangs direkt in diese Klasse einfügen. Wenn Sie svcutil.exe verwenden, um die Dienstvertragsschnittstelle zu generieren, müssen Sie diese Klasse selbst implementieren. Der folgende Code zeigt die WCF-Dienstklasse, die vom Add Adapter Service Reference Plug-In generiert wurde.
namespace OracleDBBindingNamespace {
public class OracleDBBindingService : POLLINGSTMT_OperationGroup {
// CODEGEN: Generating message contract since the wrapper namespace (http://Microsoft.LobServices.OracleDB/2007/03/POLLINGSTMTAcctActivity)
// of message POLLINGSTMT does not match the default value (http://Microsoft.LobServices.OracleDB/2007/03)
public virtual void POLLINGSTMT(POLLINGSTMT request) {
throw new System.NotImplementedException("The method or operation is not implemented.");
}
}
}
Empfangen des POLLINGSTMT-Vorgangs
So empfangen Sie Abrufdaten vom Oracle Database-Adapter
Verwenden Sie das Add Adapter Service Reference Plug-In oder svcutil.exe, um einen WCF-Dienstvertrag (Schnittstelle) und Hilfsklassen für den POLLINGSTMT-Vorgang zu generieren. Weitere Informationen finden Sie unter Generieren eines WCF-Clients oder eines WCF-Dienstvertrags für Oracle Database-Lösungsartefakte. Mindestens müssen Sie die Eigenschaft PollingStatement-Bindung festlegen, wenn Sie eine Verbindung mit dem Adapter herstellen. Optional können Sie einen PollingId-Parameter im Verbindungs-URI angeben. Wenn Sie das Add Adapter Service Reference Plug-In verwenden, sollten Sie alle Bindungsparameter festlegen, die für Ihre Konfiguration erforderlich sind. Dadurch wird sichergestellt, dass sie in der generierten Konfigurationsdatei ordnungsgemäß festgelegt werden.
Implementieren Sie einen WCF-Dienst aus der In Schritt 1 generierten Schnittstellen- und Hilfsklassen. Die POLLINGSTMT-Methode dieser Klasse kann eine Ausnahme auslösen, um die Abfragetransaktion abzubrechen, wenn ein Fehler bei der Verarbeitung der vom POLLINGSTMT-Vorgang empfangenen Daten auftritt. andernfalls gibt die Methode nichts zurück. Sie müssen die WCF-Dienstklasse wie folgt zuordnen:
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]
Wenn Sie das Add Adapter Service Reference Plug-In zum Generieren der Schnittstelle verwendet haben, können Sie Ihre Logik direkt in der POLLINGSTMT-Methode in der generierten OracleDBBindingService-Klasse implementieren. Diese Klasse finden Sie in OracleDBBindingService.cs. Dieser Code in diesem Beispiel unterordnet die OracleDBBindingService-Klasse .
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)] public class PollingStmtService : OracleDBBindingService { public override void POLLINGSTMT(POLLINGSTMT request) { Console.WriteLine("\nNew Polling Records Received"); Console.WriteLine("Tx Id\tAccount\tAmount\tDate\t\t\tDescription"); for (int i = 0; i < request.POLLINGSTMTRECORD.Length; i++) { Console.WriteLine("{0}\t{1}\t{2}\t{3}\t{4}", request.POLLINGSTMTRECORD[i].TID, request.POLLINGSTMTRECORD[i].ACCOUNT, request.POLLINGSTMTRECORD[i].AMOUNT, request.POLLINGSTMTRECORD[i].TRANSDATE, request.POLLINGSTMTRECORD[i].DESCRIPTION); } } }
Wenn Sie zum Generieren der Schnittstelle svcutil.exe verwendet haben, müssen Sie einen WCF-Dienst erstellen, der die Schnittstelle implementiert und Ihre Logik in der POLLINGSTMT-Methode dieser Klasse implementiert.
Erstellen Sie eine instance des WCF-Diensts, der in Schritt 2 erstellt wurde.
// create service instance PollingStmtService pollingInstance = new PollingStmtService();
Erstellen Sie eine instance von System.ServiceModel.ServiceHost mithilfe des WCF-Diensts und eines Basisverbindungs-URI. Der Basisverbindungs-URI darf keine userinfoparams oder einen query_string enthalten.
// Enable service host Uri[] baseUri = new Uri[] { new Uri("oracledb://Adapter") }; ServiceHost srvHost = new ServiceHost(pollingInstance, baseUri);
Erstellen Sie eine OracleDBBinding-Instanz , und konfigurieren Sie den Abrufvorgang, indem Sie dessen Bindungseigenschaften festlegen. Sie können dies entweder explizit im Code oder deklarativ in der Konfiguration tun. Mindestens müssen Sie die Abfrage-Anweisung und das Abfrageintervall angeben. In diesem Beispiel geben Sie die Anmeldeinformationen als Teil des URI an, sodass Sie auch acceptCredentialsInUri auf true festlegen müssen.
// Create and configure a binding for the service endpoint. NOTE: binding // parameters are set here for clarity, but these are already set in the // the generated configuration file OracleDBBinding binding = new OracleDBBinding(); // The credentials are included in the connection URI, so set this property to true binding.AcceptCredentialsInUri = true; // Same as statement specified in Configure Adapter dialog box binding.PollingStatement = "SELECT * FROM ACCOUNTACTIVITY FOR UPDATE"; binding.PostPollStatement = "BEGIN ACCOUNT_PKG.PROCESS_ACTIVITY(); END;"; // Be sure to set the interval long enough to complete processing before // the next poll binding.PollingInterval = 15; // Polling is transactional; be sure to set an adequate isolation level // for your environment binding.TransactionIsolationLevel = TransactionIsolationLevel.ReadCommitted;
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 bei Bedarf eine PollingId enthält.
Geben Sie den Vertrag als "POLLINGSTMT_OperationGroup" an.
// Add service endpoint: be sure to specify POLLINGSTMT_OperationGroup as the contract Uri serviceUri = new Uri("oracledb://User=SCOTT;Password=TIGER@Adapter?PollingId=AcctActivity"); srvHost.AddServiceEndpoint("POLLINGSTMT_OperationGroup", binding, serviceUri);
Um Abrufdaten zu empfangen, öffnen Sie den Diensthost. Der Adapter gibt Daten zurück, wenn die Abfrage ein Resultset zurückgibt.
// Open the service host to begin polling srvHost.Open();
Um die Abfrage zu beenden, schließen Sie den Diensthost.
Wichtig
Der Adapter ruft weiterhin ab, bis der Diensthost geschlossen wird.
srvHost.Close();
Beispiel
Das folgende Beispiel zeigt eine Abfrage, die für die Tabelle /SCOTT/ACCOUNTACTIVITY ausgeführt wird. Die Anweisung nach der Abfrage ruft eine Oracle-Funktion auf, die die verarbeiteten Datensätze in eine andere Tabelle /SCOTT/ACCOUNTHISTORY verschiebt. Der Namespace des POLLINGSTMT-Vorgangs wird geändert, indem der PollingId-Parameter im Verbindungs-URI auf "AccountActivity" festgelegt wird. In diesem Beispiel wird der WCF-Dienst für den POLLINGSTMT-Vorgang erstellt, indem die generierte OracleDBBindingService-Klasse untergeordnet wird. Sie können Ihre Logik jedoch direkt in der generierten Klasse implementieren.
using System;
using System.Collections.Generic;
using System.Text;
// Add these three references to use the Oracle adapter
using System.ServiceModel;
using Microsoft.ServiceModel.Channels;
using Microsoft.Adapters.OracleDB;
using microsoft.lobservices.oracledb._2007._03.POLLINGSTMTAcctActivity;
using OracleDBBindingNamespace;
namespace OraclePollingSM
{
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]
public class PollingStmtService : OracleDBBindingService
{
public override void POLLINGSTMT(POLLINGSTMT request)
{
Console.WriteLine("\nNew Polling Records Received");
Console.WriteLine("Tx Id\tAccount\tAmount\tDate\t\t\tDescription");
for (int i = 0; i < request.POLLINGSTMTRECORD.Length; i++)
{
Console.WriteLine("{0}\t{1}\t{2}\t{3}\t{4}", request.POLLINGSTMTRECORD[i].TID,
request.POLLINGSTMTRECORD[i].ACCOUNT,
request.POLLINGSTMTRECORD[i].AMOUNT,
request.POLLINGSTMTRECORD[i].TRANSDATE,
request.POLLINGSTMTRECORD[i].DESCRIPTION);
}
Console.WriteLine("\nHit <RETURN> to stop polling");
}
}
class Program
{
static void Main(string[] args)
{
ServiceHost srvHost = null;
// This URI is used to specify the address for the ServiceEndpoint
// It must contain credentials and the PollingId (if any) that was used to generate
// the WCF service callback interface
Uri serviceUri = new Uri("OracleDb://User=SCOTT;Password=TIGER@Adapter?PollingId=AcctActivity");
// This URI is used to initialize the ServiceHost. It cannot contain
// userinfoparms (credentials) or a query_string (PollingId); otherwise,
// an exception is thrown when the ServiceHost is initialized.
Uri[] baseUri = new Uri[] { new Uri("OracleDb://Adapter") };
Console.WriteLine("Sample started, initializing service host -- please wait");
// create an instanc of the WCF service callback class
PollingStmtService pollingInstance = new PollingStmtService();
try
{
// Create a ServiceHost with the service callback instance and a base URI (address)
srvHost = new ServiceHost(pollingInstance, baseUri);
// Create and configure a binding for the service endpoint. Note: binding
// parameters are set here for clarity but these are already set in the
// generated configuration file
//
// The following properties are set
// AcceptCredentialsInUri (true) to enable credentials in the connection URI for AddServiceEndpoint
// PollingStatement
// PostPollStatement calls PROCESS_ACTIVITY on Oracle. This procedure moves the queried records to
// the ACCOUNTHISTORY table
// PollingInterval (15 seconds)
// TransactionIsolationLevel
OracleDBBinding binding = new OracleDBBinding();
// The Credentials are included in the Connection Uri so set this property true
binding.AcceptCredentialsInUri = true;
// Same as statement specified in Configure Adapter dialog box
binding.InboundOperationType = InboundOperation.Polling;
binding.PollingStatement = "SELECT * FROM ACCOUNTACTIVITY FOR UPDATE";
binding.PostPollStatement = "BEGIN ACCOUNT_PKG.PROCESS_ACTIVITY(); END;";
// Be sure to set the interval long enough to complete processing before
// the next poll
binding.PollingInterval = 15;
// Polling is transactional, be sure to set an adequate isolation level
// for your environment
binding.TransactionIsolationLevel = TransactionIsolationLevel.ReadCommitted;
// Add service endpoint: be sure to specify POLLINGSTMT_OperationGroup as the contract
srvHost.AddServiceEndpoint("POLLINGSTMT_OperationGroup", binding, serviceUri);
Console.WriteLine("Opening the service host");
// Open the service host to begin polling
srvHost.Open();
// Wait to receive request
Console.WriteLine("\nPolling started. Returned records will be written to the console.");
Console.WriteLine("Hit <RETURN> to stop polling");
Console.ReadLine();
}
catch (Exception e)
{
Console.WriteLine("Exception :" + e.Message);
Console.ReadLine();
/* If there is an Oracle 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 (srvHost.State == CommunicationState.Opened)
srvHost.Close();
else
srvHost.Abort();
}
}
}
}
Weitere Informationen
Entwickeln von Oracle Database-Anwendungen mithilfe des WCF-Dienstmodells