The following is sample code developed in a Console application that demonstrates how to use the WCF SQL Server Adapter for notification services outside of BizTalk. This example, based on the WCF Service Model, can be modified and extended to run as a Windows Service or as a long-running service in the Windows Server AppFabric.
Program class
using System;
using System.ServiceModel;
using System.ServiceModel.Description;
using System.Collections.ObjectModel;
using System.ServiceModel.Channels;
namespace Test.NotificationOutsideBTS
{
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]
class
NotificationNetworkCredentials : 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
NotificationNetworkCredentials();
clone.Windows.ClientCredential = this.Windows.ClientCredential;
return clone;
}
}
public
class
NotificationAction
{
public
Action<Notification> ProcessNotification = delegate(Notification message)
{
Console.WriteLine("\nNotification arrived:");
Console.WriteLine("-->Info: {0}", message.Info);
Console.WriteLine("-->Source: {0}", message.Source);
Console.WriteLine("-->Type: {0}", message.Type);
Console.WriteLine("\nWaiting for notification (press any key to stop the service)...");
};
}
class
Program
{
static
void Main(string[] args)
{
ServiceHost svcHost = null;
try
{
Console.WriteLine("Registering Notification listener...");
Uri[] svcUri = new
Uri[] { new
Uri("mssql://EWT//MyDatabaseName") };
svcHost = new
ServiceHost(typeof(SqlAdapterBindingNamespace.SqlAdapterBindingService), svcUri);
NotificationNetworkCredentials credentials = new
NotificationNetworkCredentials();
credentials.Windows.ClientCredential = System.Net.CredentialCache.DefaultNetworkCredentials;
svcHost.Description.Behaviors.Add(credentials);
svcHost.Open();
Console.WriteLine("Service Host and Listener opened...");
Console.WriteLine("Waiting for notification (press any key to stop the service)...");
Console.ReadKey();
}
catch (Exception ex)
{
Console.WriteLine(ex);
Console.ReadKey();
}
finally
{
if (svcHost.State == CommunicationState.Opened)
svcHost.Close();
else
svcHost.Abort();
}
}
}
}
The following are the sqlBinding service notification classes generated with the Add Adapter Service Reference wizard using Service (Inbound operations) as the contract type:
SqlAdapterBindingInterface class
[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 (http://schemas.microsoft.com/Sql/2008/05/Notification/) of message Notification does not match the default value (http://schemas.microsoft.com/Sql/2008/05/)
[System.ServiceModel.OperationContractAttribute(IsOneWay=true, Action="Notification")]
void Notification(Notification request);
}
[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;
}
}
SqlAdapterBindingService class
using Test.NotificationOutsideBTS;
namespace SqlAdapterBindingNamespace {
public
class
SqlAdapterBindingService : NotificationOperation {
// CODEGEN: Generating message contract since the wrapper namespace (http://schemas.microsoft.com/Sql/2008/05/Notification/) of message Notification does not match the default value (http://schemas.microsoft.com/Sql/2008/05/)
public
virtual
void Notification(Notification request) {
//throw new System.NotImplementedException("The method or operation is not implemented.");
NotificationAction action = new
NotificationAction();
action.ProcessNotification(request);
}
}
}
In this sqlBinding service class, we simply commented out the NotImplementedException and added an Action delegate, which is coded in the main program class.
ServiceModel Configuration
The following is the configuration generated by the wizard based on the input values provided:
<behaviors>
<endpointBehaviors>
<behavior
name="InboundActionEndpointBehavior">
<inboundActionElement />
</behavior>
</endpointBehaviors>
</behaviors>
<extensions>
<behaviorExtensions>
<add
name="inboundActionElement"
type="Microsoft.ServiceModel.Channels.InboundActionElement, Microsoft.ServiceModel.Channels, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
</behaviorExtensions>
</extensions>
<services>
<service
name="SqlAdapterBindingNamespace.SqlAdapterBindingService">
<endpoint
address="mssql://ewt//MyDatabase?InboundId=MyNotification"
behaviorConfiguration="InboundActionEndpointBehavior"
binding="sqlBinding"
bindingConfiguration="SqlAdapterBinding"
contract="NotificationOperation" />
</service>
</services>
<bindings>
<sqlBinding>
<binding
name="SqlAdapterBinding"
closeTimeout="00:01:00"
openTimeout="00:01:00"
receiveTimeout="00:10:00"
sendTimeout="00:01:00"
maxConnectionPoolSize="100"
encrypt="false"
workstationId=""
useAmbientTransaction="true"
batchSize="20"
polledDataAvailableStatement=""
pollingStatement=""
pollingIntervalInSeconds="30"
pollWhileDataFound="false"
notificationStatement="SELECT ID FROM dbo.MyTable"
notifyOnListenerStart="true"
enableBizTalkCompatibilityMode="true"
chunkSize="4194304"
inboundOperationType="Notification"
useDatabaseNameInXsdNamespace="false"
allowIdentityInsert="false"
enablePerformanceCounters="false"
xmlStoredProcedureRootNodeName=""
xmlStoredProcedureRootNodeNamespace="" />
</sqlBinding>
</bindings>
Console Output
Sample output when the notification listener starts:
Registering Notification listener...
Service Host and Listener opened...
Waiting for notification (press any key to stop the service)...
Notification arrived:
-->Info: ListenerStarted
-->Source: SqlBinding
-->Type: Startup
Waiting for notification (press any key to stop the service)...
Output if an insert occurs in the database that matches the notification statement:
Notification arrived:
-->Info: Insert
-->Source: Data
-->Type: Change
Waiting for notification (press any key to stop the service)...