Understanding the New BizTalk Adapter for SQL Server
Table of Contents
1. SQL Adapter Architecture
2. Connecting to the SQL Server
3. What operations can be performed using SQL Adapter
Features supported by the SQL Adapter
New features
Limitations of BizTalk Adapter for SQL Server
4. Difference between “Add Adapter” and “Consume Adapter Service” generated outputs
Working with simple select operation
How to change the binding file generated by “Consume Adapter Service” to make it work for WCF SQL
adapter
5. Composite Operations
Composite operations
Test other operations
6. SQL Adapter Migration Tutorial
Migrating old SQL adapter project to use WCF SQL Adapter
Configuring dynamic ports
7. Polling for SQL Adapter
Polling
8. Notification for SQL Adapter
Notification
1
SQL Adapter Architecture
Architecture of BizTalk Adapter for SQL Server
The Microsoft BizTalk Adapter for SQL Server is a Windows Communication Foundation (WCF) custom binding. This
binding contains a single custom transport binding element that enables communication with a SQL Server database.
The SQL adapter is wrapped by the Microsoft Windows Communication Foundation (WCF) Line of Business (LOB)
Adapter SDK run time and is exposed to applications through the WCF channel architecture. The SQL adapter
communicates with the SQL Server database through ADO.NET 3.5.
The following figure shows the end-to-end architecture for solutions that are developed by using the SQL adapter:
2
The Microsoft BizTalk Adapter for SQL Server exposes a WCF custom binding, the SQL DB Binding
(Microsoft.Adapters.SQLDB.SQLDBBinding). By default, this binding contains a single custom transport binding element,
3
the SQL DB Adapter Binding Element (Microsoft.Adapters.SQLDB.SQLDBAdapter), which enables operations on a SQL
Server database.
Microsoft.Adapters.SQLDB.SQLDBBinding (the SQL DB Binding) and Microsoft.Adapters.SQLDB.SQLDBAdapter (the
SQL DB Adapter Binding Element) are public classes and are also exposed to the configuration system. Because the SQL
DB Adapter Binding Element is exposed publicly, you can build your own custom WCF bindings capable of extending the
functionality of the SQL adapter. For example, you could implement a custom binding to support Enterprise Single Signon (SSO) in a WCF channel or service model solution. The reasons for doing this would be to aggregate database
operations into a single multifunction operation or to perform schema transformation between operations implemented
by a custom application and operations on the SQL Server database.
The SQL adapter is built on top of the Microsoft Windows Communication Foundation (WCF) Line of Business (LOB)
Adapter SDK, and runs on top of the WCF LOB Adapter SDK run time. The WCF LOB Adapter SDK provides a software
framework and tooling infrastructure that the SQL adapter uses to provide a rich set of features to users and adapter
clients.
The WCF LOB Adapter SDK serves as the software layer through which the SQL adapter interfaces with the WCF;
ADO.NET serves as the layer through which the SQL adapter interfaces with the SQL Server database. The following
figure shows the relationships between the internal components of the SQL adapter and WCF:
4
5
Connecting to the SQL Server
Create a new BizTalk project:
Right Click on the project name in the solution explorer – Add – Add Generated Items – Add Adapter Metadata.
Click on Add button.
Select WCF-SQL adapter from the list and click on the Next.
On the Consume Adapter Service screen, by default sqlBinding will be selected for you.
Now configure connection URI. The URI has the following format:
mssql://[Server_Name]/[Database_Instance_Name]/[Database_Name]?FailoverPartner=[Par
tner_Server_Name]&InboundId=[Inbound_ID]
Click on the Configure button.
Security Tab:
Provide credentials as Windows or SQL user name / password
URI Properties:
Server
InstanceName (optional)
InitialCatalog (optional)
SQL Server name
SQL Server Instance Name
database name
FailoverPartner (optional)
In the connection URI, you can also specify the name of a failover SQL Server database on a standby computer to
connect to if the primary SQL Server database is not available. The failover SQL Server database must be a
mirror of the primary SQL Server database. The failover SQL Server database is specified using an optional
parameter, FailoverPartner, in the connection URI. Providing a failover SQL Server database ensures high
availability and data redundancy. For more information about high availability with respect to SQL Server, see
“Using Database Mirroring” at http://go.microsoft.com/fwlink/?LinkId=116733.
InboundID (optional)
Consider a scenario where you want to create a BizTalk application that includes two polling operations. Each
polling operation polls separate tables, Employee and Customer, from the same database. When you deploy
such an application in BizTalk Server Administration console, you will need to create two receive ports. The
connection URI for each receive port will be:
mssql://<server_name>/<database_instance_name>/<datbase_name>
Because both receive ports are receiving polling messages from the same database on the same server, the
connection URI for both will be the same. However, a BizTalk application cannot have two receive ports with the
same connection URI.
To enable adapter clients to have two receive ports that poll the same database (or even the same table in a
database) in a BizTalk application, the SQL adapter provides a connection property, InboundID. You can specify
any value for this connection property. By adding the inbound ID, a connection URI becomes unique.
For example, the connection URI for the port receiving polling messages for the Employee table can be:
mssql://<server_name>/<database_instance_name>/<datbase_name>?InboundID=Employee
Similarly, the connection URI for the port receiving polling messages for the Customer table can be:
6
mssql://<server_name>/<database_instance_name>/<datbase_name>?InboundID=Customer
Because the connection URIs become unique by adding the InboundID property, you can now have multiple
receive ports polling the same database or table in a single BizTalk application.
Binding Properties
For time being we will leave this section. We will discuss those properties as we come across those.
Note:
Some adapters support the AcceptCredentialsInUri Binding Property. This property will not be displayed on the
property page and by default it is set to false. If you pass credential in the URI, adapter will throw an exception.
If you set this property to true, no exception is thrown and credentials are passed as plain text.
As this is a big security risk, the SQL adapter does not support AcceptCredentialsInUri binding property.
Credentials are never permitted in the connection URI.
After providing Security and URI properties on the configure Adapter screen click OK and on the Consume
Adapter Service screen click Connect.
SQL Server Operations
Now you can define two types of operations while in the Consume Adapter Service screen:
Client (Outbound operations)
Service (Inbound operations)
Whenever you see “Typed” prefix, what it really means is schema information is available during design time. It helps
when you want to directly map the message coming from SQL to some other schema.
7
What operations can be performed using SQL Adapter
Performing Basic Insert, Update, Delete, and Select Operations on Tables and Views
You can perform DML operations conforming to the SQL rules and limitations. You can make use of the “WHERE” clause
to restrict the number of rows being operated.
Executing Scalar and Table Valued Functions in SQL Server
This will again require more of a SQL understanding rather than BizTalk. The Transact-SQL and CLR functions in SQL
Server are surfaced as operations in WCF-SQL adapter. The operation name in the adapter is the same as the name of
the function in SQL Server. All the parameters in the function are exposed in the corresponding operation.
Executing Stored Procedures in SQL Server
The Transact-SQL and CLR stored procedures in SQL Server are surfaced as operations under the Procedures node. The
operation names exposed by the SQL adapter are the same as the name of the stored procedure in SQL Server. All the
parameters in the stored procedure are exposed in the corresponding operation. The OUT parameter contains the
return value of the stored procedure. The result set of the stored procedure is an array of DataSet.
The procedures listed under “Strongly-Typed Procedures” node are the same as that of listed under “Procedures” node.
The difference is, in case of “Procedures”, the schema information of the target object is obtained as part of the
response message at run time. Where as in case of “Strongly-Typed Procedures” node, the return value of the stored
procedure is strongly typed, and not just an array of DataSet - the schema information is available at the design time.
You can also execute stored procedures that have a SELECT statement with a FOR XML clause. A FOR XML clause is used
in a SELECT statement to return the results as XML instead of a rowset. The old SQL adapter supports stored procedures
with FOR XML clause only. So you can use the old SPs along with new WCF-SQL adapter without making any changes.
Note:
In general, it is recommended that all the columns in a result set for stored procedures and strongly-typed stored
procedures must be named, and have unique names. If you don’t specify names to the columns, the adapter will try to
use its own convention. In case of strongly-typed procedures, the column names in a result set must have unique names
– otherwise the adapter will throw an exception.
Executing ExecuteNonQuery, ExecuteReader, and ExecuteScalar Operations
ExecuteNonQuery: Use this operation to execute any arbitrary SQL statements in SQL Server if you do not want any
result set to be returned. The return value of this operation is of Int32 data type, and indicates the number of affected
rows as a result of executing the SQL statements.
ExecuteReader: Use this operation to execute any arbitrary SQL statements in SQL Server if you want the result set to be
returned, if any, as an array of DataSet.
ExecuteScalar: Use this operation to execute any arbitrary SQL statements in SQL Server to return only the first column
of the first row in the result set returned by the query.
The advantage of ExecuteScalar over ExecuteReader is that the response message payload of the ExecuteScalar
operation is much smaller compared to the one returned by the ExecuteReader operation. Therefore, if you require only
one value to be returned, you should use ExecuteScalar instead of ExecuteReader.
Operations on Tables and Views That Contain Large Data Types
The WCF-SQL adapter provides support for the following SQL Server large data types:
Varchar(Max)
8
Nvarchar(Max)
Varbinary(Max)
To read large data values from SQL Server, the adapter exposes the Select operation.
To write large data values to SQL Server, the SQL adapter exposes the Set<column_name> operation, where
<column_name> is the name of the column of type Varchar(Max), Nvarchar(Max) or Varbinary(Max).
The Set<column_name> operation also allows adapter clients to write FILESTREAM data in SQL Server 2008.
The Set<column_name> operation is available only for those tables and views that contain columns with any of the
three large data types.
Support for Composite Operations
The adapter enables clients to perform composite operations on the SQL Server database.
A composite operation can include any number of the following operations, and in any order:
The Insert, Update, and Delete operations on the tables and views.
Stored procedures that are surfaced as operations in the adapter.
The operations in a composite operation can target tables and views in the same database or different databases.
However, data cannot be shared or reused across different operations in a composite operation. For example, in a
composite operation, the result set of a Select operation cannot be used as the input parameter for a stored procedure.
Important:
If there are “n” number of operations in a composite operation that return a result set then “n+1” number of
connections are required for the composite operation to be executed. Therefore, you must ensure that the value
specified for the MaxConnectionPoolSize binding property is n+1 or greater.
Support for Polling
The adapter enables clients to receive data-change messages from the SQL Server database. The adapter supports
receiving "polling-based" messages wherein the adapter executes a specified SQL statement (SELECT statement or
stored procedure), retrieves or updates the data, and provides the result to the adapter client at regular intervals of
time.
The SQL adapter exposes the following operations for polling:
Polling: Enables you to receive periodic data-change messages for SQL Server tables or views. The messages
are not strongly-typed.
TypedPolling: Enables you to receive strongly-typed messages from the SQL Server database. You must use this
operation if you intend to map the elements in the polling message to any other schema.
XmlPolling: Enables you to use SELECT statements or stored procedures that use a FOR XML clause and return
data as XML messages. This operation returns the polling message as an XML message.
Receiving Query Notifications
The adapter clients can subscribe to receive query notifications about the data changes in the SQL Server database. A
SQL SELECT statement or a stored procedure specifies the data-change criteria in a table for triggering of the query
notifications, and the SQL Server sends query notifications as and when the result set for the SELECT statement or the
stored procedure changes.
Important:
9
To support query notifications, the adapter clients and the SQL Server database have to fulfill certain requirements. For
detailed information about these requirements, see “Enabling Query Notifications” at
http://go.microsoft.com/fwlink/?LinkID=122323
Support for invoking artifacts with same name in different databases
In the SQL adapter, the namespaces in the XML Schema Definition (XSD) file contained only the schema name, and in
some cases the object name. However, if an application wants to execute operations on identically named artifacts with
different metadata in different databases, the generated metadata will conflict. The only way to distinguish the
metadata is to use the database name in the XSD namespaces.
The adapter allows you to specify the database name in the XSD namespaces by setting the value of the
UseDatabaseNameInXsdNamespace binding property to TRUE. The default value of the binding property is false, which
implies that the XSD namespaces will not contain the database name.
Support for performing operations on artifacts in multiple schemas
Apart from the default schema (dbo), adapter clients can also perform operations on artifacts in other schemas in the
SQL Server database provided that the user credentials used to connect using the SQL adapter has access to those
schemas in the SQL Server database.
UDT
You can use the adapter to perform all the operations on tables or views that have columns of user-defined-types
(UDTs). You can use the standard operations to read or write data into UDT columns. You can use functions / stored
procedures as well. Before using those operations, you have to make sure that the assemblies for the UDTs are GACed
appropriately and are available at the correct installation path for the BizTalk server operations.
And lastly, there are a few limitations as well
Limitations
1. The WCF-SQL adapter schema is not compatible with the schema of the SQL adapter available with BizTalk
Server 2006. The WCF-SQL adapter does not support sending and receiving messages having schemas that were
generated by using the earlier version of the adapter. However, in one of the following sessions, we will take an
example to migrate existing BizTalk projects using legacy SQL adapter to use the new WCF-SQL adapter.
2. The WSDL the SQL adapter generates, when converted to a proxy, exposes the DateTimeOffset column as
System.DateTime. This data type cannot store time zone information. As a consequence, any date/time value
the adapter sends to the proxy will be converted into local time in the .NET application. If you wish to keep the
time zone information, you must change the interface of your proxy to use the String type instead of
System.DateTime. Then, use XmlConvert.ToDateTimeOffset to create a Sytstem.DateTimeOffset object, which
can store the timezone information.
3. The SQL adapter does not support synonyms created in the SQL Server database.
4. If a parameter name in a stored procedure contains 127 or more characters, you cannot execute the stored
procedure using the SQL adapter. This is due to the limitation of ADO.NET.
10
“Add Adapter” and “Consume Adapter Service” generated outputs
In this session:
1. We will look at the difference between “Add Adapter Metadata” and “Consume Adapter Service” generated
outputs
2. Perform a simple Select operation
3. Find out how to change the binding file generated by consume adapter service to make it work for WCF-SQL
Adapter (reusing Adapter Bindings)
We need a sample database AdventureWorks, which you can download from
http://www.codeplex.com/SqlServerSamples. For the sample BizTalk project, we will use a simple flow:
1.
2.
3.
4.
Receive message from the file pick up location
Send request to the SQL server – AdventureWorks database
Receive response back from the SQL server
Send response message to the file location
Here is a sample view:
Add Adapter Metadata Sample
1. Create a new BizTalk project named AdapterSelectSample.
2. Right click on the project name – Add – Add Generated Items – Add Adapter Metadata and click on Add.
11
3. Select WCF-SQL from the list and click on Next.
4. Click on Configure:
a. Security
i. Client credential = Windows
b. URI Properties
i. Initial catalog = AdventureWorks
ii. Server = localhost
5. Click on Connect. From Select Category tree view, expand tables – Select [HumanResources].[Employee].
6. From right side section, select “Select” operation and click on Add and then Click on Ok.
7. You will see a very familiar scenario for the BizTalk developer:
3 schemas are added along with a BizTalk orchestration.
Open each schema and analyze it.
8. Open the orchestration and add respective Receive and Send shapes.
9. Right click on the port surface Select New configured port. Click on Next .
10. Provide the port name and click on Next.
11. Select “Use an existing Port Type” and from available ports select
AdapterSelectSample.TableOp_HumanResources_Employee.
12. Click on Next. Select “I will be sending a request and receiving a response” and “Specify later”.
13. Click on Next and Finish.
14. Select operations for the LOB Port:
Request is of Multi-part message type
AdapterSelectSample.TableOp_HumanResources_Employee_Select_InputMessage
Response is of Multi-part message type
AdapterSelectSample.TableOp_HumanResources_Employee_Select_OutputMessage
15. In the orchestration view, create two message InputMessage and OutputMessage:
Input message = Multi-part message types AdapterSelectSample.TableOp_HumanResources_Employee_Select_InputMessage
Output message = Multi-part message types AdapterSelectSample.TableOp_HumanResources_Employee_Select_OutputMessage
16. Add ports for Request Message and Response Message. Associate Receive and Send shapes with
appropriate message types.
17. Compile and deploy the project.
18. Add Solicit-Response Send port. Select Type as WCF-SQL.
Select XML pipeline for Send and Receive.
Click on Configure. For the Address URI specify Initial Catalog = AdventurWorks and Server = localhost.
Specify SOAP action as TableOp/Select/HumanResources/Employee.
19. Bind the ports and start the application.
20. To test the solution, you can use the following message:
<ns0:Select
xmlns:ns0="http://schemas.microsoft.com/Sql/2008/05/TableOp/HumanResources/Emplo
yee">
<ns0:Columns>*</ns0:Columns>
<ns0:Query>WHERE EmployeeID=1</ns0:Query>
</ns0:Select>
Note:
Some of the SQL server collations are case sensitive for object names as well. You might get “Invalid column name”
error message. Make sure that the column names are spelled with the correct case.
This request message will retrieve records from the Employee table that satisfy the condition specified in the <Query>
element. If you want to retrieve specific columns from the table, you must specify them in the <Columns> element,
12
separated by comma, in the same sequence as they appear in the table definition. If you do not want to specify a
condition to retrieve data, leave the <Query> element blank. From the WCF-SQL Adapter help file, see Message
Schemas for Basic Insert, Update, Delete, and Select Operations on Tables and Views for more information about the
request message schema for performing basic DML operations on SQL Server database tables and views using the SQL
adapter.
Consume Adapter Service Sample
Before proceeding, just remove the previous assembly from the BizTalk Administration and any associated ports to avoid
the confusion:
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
Create a new BizTalk project named AdapterSelectSample.
Right click on the project name – Add – Add Generated Items – Consume Adapter Service and click on Add.
Select sqlbinding from the binding list.
Click on Configure:
a. Security
i. Client credential = Windows
b. URI Properties
i. Intial catalog = AdventureWorks
ii. Server = localhost
Click on connect. From Select Category tree view, expand tables – Select [HumanResources].[Employee].
From right side section, select “Select” operation and click on Add and then Click on Ok.
3 schemas are added along with a binding file and there is NO BizTalk orchestration. Open each schema and
analyze it. Compare schemas with the AdapterSelectSample project schemas. Just a naming convention
difference.
Open the orchestration and add respective Receive and Send shapes.
Right click on the port surface Select New configured port. Click on Next.
Provide the port name and click on Next.
Select “Use an existing Port Type”. Notice that there are no available ports. Select Create a New Port Type.
Communication pattern is Request-Response.
Click on Next. Select “I will be sending a request and receiving a response” and “Specify later”.
Click on Next and Finish.
In the orchestration view, create two message InputMessage and OutputMessage:
Input message = Schemas - AdapterSelectSample.TableOp_HumanResources_Employee.Select
Output message = Schemas AdapterSelectSample.TableOp_HumanResources_Employee.SelectResponse
Compare this carefully with the AdapterSelectSample project – no multipart message.
15. Add ports for Request Message and Response Message. Associate Receive and Send shapes with
appropriate message types.
16. Compile and deploy the project.
17. In the BizTalk Administration console, right click on the application name where you deployed the project
and select Import Binding. Point to the file WcfSendPort_SqlAdapterBinding_Custom.bindinginfo and
complete the import operation. Check that the Solicit-Response WCF-SQL Send port is added
WcfSendPort_SqlAdapterBinding_TableOp_HumanResources_Employee_Custom.
18. Bind the ports and start the application.
19. Test the solution using the same input message – Why am I getting the error like this?
The adapter failed to transmit message going to send port
"WcfSendPort_SqlAdapterBinding_TableOp_HumanResources_Employee_Custom" with
13
URL "mssql://localhost//AdventureWorks?". It will be retransmitted after the
retry interval specified for this Send Port.
Details:"Microsoft.ServiceModel.Channels.Common.UnsupportedOperationException:
The action "<BtsActionMapping
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Operation Name="Select" Action="TableOp/Select/HumanResources/Employee" />
</BtsActionMapping>" was not understood.
By default, the action on the send port is mapped to the operation name for which you generated metadata.
For example, if you generate metadata for the Select operation on the Customer table, the action on the
port is set to <Operation Name="Select" Action="TableOp/Select/dbo/Customer" />. However, the
operation name on the logical send port you create in the BizTalk orchestration might not be the same. You
must ensure that the operation name in the logical send port (in the BizTalk orchestration) and the physical
send port (in BizTalk Server Administration console) are the same. If not, you will receive an error while
sending messages to SQL Server through the send port.
Here is a good blog about it - http://blogs.msdn.com/adapters/archive/2007/12/26/why-does-the-adaptersay-action-is-not-understood-even-though-i-am-using-the-binding-file-generated-by-the-consume-adapterservice-wizard.aspx.
20. So either you change the operation name in the orchestration and re-deploy the solution or
Modify the SOAP action to reflect the actual operation name –e.g.
<Operation Name="Operation_1" Action="TableOp/Select/HumanResources/Employee" />
Test the solution again.
Reusing Binding file
Here is one more feature to make the life easier for the BizTalk developer – you can modify the binding file generated by
“Consume Adapter Service” wizard just by doing “Find / Replace” in a notepad and use it for the WCF-SQL adapter
binding.
To use the same port binding file generated by the “Consume Adapter Service” wizard to create the BizTalk WCF-SQL
port perform the following tasks:
1. Open the port binding file in a text editor.
2. Search and replace “WCF-Custom” with the name with which you added the WCF-SQL adapter in BizTalk
Server Administration console. For example, if you added the WCF-SQL adapter as “WCF-SQL”, replace
“WCF-Custom” with “WCF-SQL”.
3. Search for the “ConfigurationClsid” attribute, and replace the existing value of the attribute with
“59B35D03-6A06-4734-A249-EF561254ECF7”.
4. Save and close the binding file.
5. Import the binding file in BizTalk Server Administration console.
By default, the port binding file for outbound operations generated by the “Consume Adapter Service” wizard always
contains definitions for a two-way send port. When you import this file in a BizTalk application, it creates a two-way
send port. However, you may have an orchestration that has a one-way send port. So, when you configure such an
orchestration and use the port created by importing the binding file, the port is not available in the list. This happens
because the logical port you created as part of the orchestration is a one-way port while the physical port created in the
orchestration is a two-way port. In such cases, you can edit the binding file to make the following changes:
In the following excerpt, change the value of the IsTwoWay property to false. Originally, this is set to true.
<SendPort Name="port_name" IsStatic="true" IsTwoWay="false" BindingOption="0">
14
And Comment out the following section highlighted in yellow:
<ReceivePipeline Name="Microsoft.BizTalk.DefaultPipelines.XMLReceive"
FullyQualifiedName="Microsoft.BizTalk.DefaultPipelines.XMLReceive,
Microsoft.BizTalk.DefaultPipelines, Version=3.0.1.0, Culture=neutral,
PublicKeyToken=token" Type="1" TrackingOption="None" Description=""/>
<ReceivePipelineData xsi:nil="true" />
For inbound operations, the port binding file will always create a one-way receive port. This is because the SQL adapter
only supports one-way receive port for inbound operations.
Now you should have understood the differences between using “Add Adapter Metadata” and “Consume Adapter
Service” and how to modify and reuse the binding file.
Based on the outcome, the developer can choose one of those actions which might be best suited to his development
style and maintenance requirements enforced by the project.
Add Adapter Metadata
Consume Adapter Service
Schemas + Orchestration
Schemas + Binding file (No orchestration)
Available Port in the orchestration
No Available ports in the orchestration
Message type is defined from Multi-part
Message type is defined from Schema
Send port created manually is generally WCF-SQL port – If you import the binding file, send port created is WCFhowever you may use WCF-Custom port as well.
Custom port. However you may use WCF-SQL port as well.
Composite Operations
In this session we will work on a “Composite Operation” Sample – achieving multiple operations within a single action.
We plan to do the following:
Insert a record in table 1 – [dbo].[EmployeeComp]
Execute a stored procedure to return some rows – [dbo].[uspGetEmployeeManagers]
Update record in table 2 – [HumanResources].[Employee]
Create a table EmployeeComp using the attached SQL script – CreateEmployeeTable.
Create a new BizTalk project CompositeOp.
Our first task is to generate schemas for various operations:
1. Right click on the project – Add – Add Generated Items – Add Adapter Metadata and click on Add.
2. Select WCF-SQL adapter and click on Next.
3. Click on Configure:
a. Security
i. Client credential = Windows
b. URI Properties
i. Initial catalog = AdventureWorks
ii. Server = localhost
4. Click on Connect.
5. From “Select a category” tree view, expand Tables and select [dbo].[EmployeeComp] table.
15
6.
7.
8.
9.
10.
11.
From right side section, select “Insert” operation and click on Add.
While on the same screen, select Procedures node from “Select a category” tree view.
From right side section, select SP “[dbo].[uspGetEmployeeManagers]” and click on Add.
From “Select a category” tree view, expand Tables and select [HumanResources].[Employee] table.
From right side section, select “Update” operation and click on Add.
On the “Consume Adapter Service” screen click on Ok.
Our second task is to create a multi node schema which will have the following definition:
“REQUEST” which is a composite request of above 3 operations
“RESPONSE” which is a composite response of above 3 operations
The node that corresponds to the request schema can have any name. The node that corresponds to the response
schema must be called <request_schema_node>Response. For this example, we will call the request schema node as
Request. So, the response schema node is called RequestResponse.
1.
2.
3.
4.
5.
6.
Right click on the project – Add – Add New Item and select Schema Files – Schema.
Name the schema as CompositeSchema.xsd and click on Add.
Rename the Root to Request.
In the tree view, Right click on <Schema> - Insert Schema Node and select Child Record.
Rename Record to RequestResponse.
Now add references to the schema generated for the different operations:
Right-click the root <Schema> node in the CompositeSchema.xsd, and click Properties.
In the Property box, click the ellipsis button (…) against the Imports property:
7. In the Imports dialog box, from the Import new schema as list, select XSD Import, and then click Add.
In the BizTalk Type Picker dialog box, expand the BizTalk project name node, expand Schemas, and then select
the schema you want to import. Click OK. For this example, add following schemas:
CompositeOp.sqlBinding_dbo_1
CompositeOp.sqlBinding_Employee
CompositeOp.sqlBinding_EmployeeComp
In the Imports dialog box, click OK.
8.
Now add the child nodes under the Request node. You must add the nodes in the same order in which you
want to perform the operations.
16
a. Right-click the Request node, point to Insert Schema Node, and then click Child Record.
b. Map the Record node to the request schema for the Insert operation on the EmployeeComp table. To
do so, right-click the Record node, and click Properties. In the Properties box, from the Data Structure
Type list, select Insert (Reference).
17
c. Repeat these steps to add nodes for the request schemas for uspGetEmployeeManagers stored
procedure and the Update operation. Add child record and map them to the corresponding schema as
mentioned:
uspGetEmployeeManagers (Reference)
Update (Reference)
9. Now add the nodes under the RequestResponse node that corresponds to the response schema for each
operation. You must add the child nodes in the same order as the child nodes under the Request node.
InsertResponse (Reference)
uspGetEmployeeManagersResponse (Reference)
UpdateResponse (Reference)
10. Save the CompositeSchema.xsd
Our third task is to work on the orchestration:
For the sample BizTalk project, we will use a simple flow as we used previously:
1.
2.
3.
4.
Receive message constituting multiple requests operations from the file pick up location.
Send requests to the SQL server – AdventureWorks database.
Receive response back from the SQL server.
Send response message to the file location.
1. Open the BizTalk orchestration. Go to the Orchestration view and create two messages:
InputMessage = Schemas – CompositeOp.CompositeSchema.Request
OutputMessage = Schemas – CompositeOp.CompositeSchema.RequestResponse
18
2. Add appropriate Receive and Send shapes.
3. Right click on the Port Surface and select New Configured Port – Click on Next:
a. Provide the port name and click on Next.
b. Provide the port type name.
c. Select Communication pattern as Request-Response and click on Next.
d. Select “I will be sending a request and receiving a response” and “Specify later” – Click on Next and
Finish.
4. Add ports for receiving the message and sending the response.
5. Associate first Receive and Send shape with the InputMessage.
6. Associate second Receive and Send shape with the OutputMessage.
7. Connect ports with appropriate shapes and deploy the project.
8. In the BizTalk Administration console, Add Solicit-Response Send port. Select Type as WCF-SQL:
a. Select XML pipeline for Send and Receive.
b. Click on Configure. For the Address URI specify Initial Catalog = AdventureWorks and Server = localhost.
c. Specify SOAP action as CompositeOperation – literally like this:
Now you can use an input message to test the solution.
19
Key points to remember
1. A composite operation can include:
a. Insert, Update, and Delete operations.
b. Stored procedures executed as operations.
A single composite operation can have any number of these operations, in any order.
2. A Select operation is not supported as part of a composite operation.
3. The operations in a composite operation can target tables and views in the same database or different
databases. However, data cannot be shared or reused across different operations in a composite operation. For
example, in a composite operation, the result set of the first operation cannot be used as the input parameter
for a stored procedure in the subsequent operation.
4. If there are “n” number of operations in a composite operation that return a result set then “n+1” number of
connections are required for the composite operation to be executed. Therefore, you must ensure that the
value specified for the MaxConnectionPoolSize binding property is n+1 or greater.
Now you should be able to test the remaining operations to get more clarity on each – most of the times you will find
that just operation names differ and at times you require more of SQL understanding to perform the task.
1.
2.
3.
4.
5.
Performing Basic Insert, Update, Delete, and Select Operations
Executing Stored Procedures
Invoking Scalar Functions
Invoking Table-valued Functions
Performing ExecuteReader, ExecuteScalar, or ExecuteNonQuery Operations
The following 2 operations are little bit special and require extra steps to get those working.
6. Performing Operations on Tables and Views with Large Data
a. The operation to enter FILESTREAM data must be performed within a transaction. So, make sure the
UseAmbientTransaction binding property is set to True on the port. (The default value is True).
b. For performing an operation to insert FILESTREAM data you must always use Windows Authentication
to connect to SQL Server. So, in the Credentials tab in the port properties dialog box, select the Do not
use single Sign-On option, and leave the user name and password blank.
7. Performing Operations on Tables with User-Defined Types
For SQL Server 2005: Make sure the respective assemblies for the UDTs are available under the BizTalk Server
installation location. For BizTalk Server 2006 R2, typically this is <installationdrive>:\Program Files\Microsoft
BizTalk Server 2006. For BizTalk Server 2009, typically this is <installation drive>:\Program Files\Microsoft BizTalk
Server 2009.
For SQL Server 2008: Make sure the respective assemblies for the UDTs are available on the computer where
you will be using the adapter to perform operations on SQL Server.
UDT Type
Location of assemblies
UDTs shipped with
SQL Server 2008,
for example,
Geography
Make sure Microsoft.SqlServer.Types.dll is added to the global assembly cache
(GAC).
Make sure SqlServerSpatial.dll is available under the BizTalk Server installation
location. For BizTalk Server 2006 R2, typically this is <installation drive>:\Program
Files\Microsoft BizTalk Server 2006. For BizTalk Server 2009, typically this is
<installation drive>:\Program Files\Microsoft BizTalk Server 2009.
20
These DLLs are available in the bin directory of the SQL Server instance you are connecting
to. Typically, the bin directory is available at <installation drive>:\Program Files\Microsoft
SQL Server\MSSQL10.<instance_name>\MSSQL\Binn.
UDTs not shipped
with SQL Server
2008 but defined
by users
Make sure the respective assemblies for the UDTs are available under the BizTalk Server
installation location.
For BizTalk Server 2006 R2, typically this is <installation drive>:\Program Files\Microsoft
BizTalk Server 2006.
For BizTalk Server 2009, typically this is <installation drive>:\Program Files\Microsoft
BizTalk Server 2009.
SQL Adapter Migration Tutorial
In this session we will see how to migrate the existing old SQL Adapter to use new WCF-SQL Adapter ports.
Important thing to notice is that the schemas are not compatible –so you cannot use the old BizTalk project / assemblies
as is. The migration involves changing old SQL adapter ports with new WCF SQL adapter ports. There are 2 ways to
achieve this.
Recreating a new project and redeploying
Make the changes in the existing project by generating metadata for desired operations using WCF SQL Adapter – either
using Add Adapter Metadata or Consume Adapter Service. People might prefer Consume Adapter Service as it generates
port binding file. If within the project you are using maps to map a message for the request going to old SQL Adapter,
you need to replace those maps to use new schema for the request going to new WCF SQL Adapter. Deploy the modified
project. Create appropriate WCF-SQL ports and complete the binding.
This approach will require end-to-end testing and may be time consuming and costly affair. But advantage is there is no
patch work and no confusion what so ever.
We have a good tool to start with for this kind of migration. Download the tool BizTalkAdapterPackMigrationTool.zip
from http://www.microsoft.com/downloads/details.aspx?FamilyID=e68b8fd1-5c8a-499a-82374dc23a8342c5&displaylang=en.
Why would someone opt to this option? Well, in the next version of BizTalk we plan to deprecate and remove the old
SQL adapter.
Without making changes to the working code
Using this approach, you can add the metadata for desired operation to the existing project (or by creating a new project
and adding reference to the old project). But do not make any changes to the existing maps / schemas.
Create transform to map a request from the old SQL Adapter to the request for the new WCF-SQL Adapter.
Create transform to map a response from the new WCF-SQL Adapter to the response for the old SQL Adapter.
If you have modified the existing project, redeploy it or deploy the new project.
Create appropriate WCF-SQL ports.
On those new WCF-SQL ports:
Add Outbound Map – and set it to a map which will transform the old SQL Adapter request to the new WCF-SQL
Adapter request
21
Add Inbound Map – and set it to a map which will transform the new WCF-SQL Adapter response to the old SQL
Adapter response.
Complete the binding and start the application.
While using this approach, if you have created separate project for maps, the advantage is you don’t have to make any
redeployment for the working applications. During deployment stage, you will have to just un-enlist orchestrations /
send ports and bind those with new WCF-SQL ports. This is easier from maintenance perspective as well – you can club
SQL operations from ‘n’ different old projects and deal those within a single project deployment. This goes well with our
traditional approach – separate out schemas and maps in a different project.
In this tutorial we will use second approach and will create a separate migration helper project for maps.
Steps for creating old SQL adapter project
1. Create new BizTalk project OLDSQLAdapter
2. Right click on the project name – Add – Add Generated Items – Add Adapter Metadata – Click on AddSelect SQL
Adapter and click on next
3. Set the connection string to connect to AdventureWorks database and click on Next
4. On Schema Information screen select the port type as Send port
5. Provide appropriate root name space and root element names – click on Next
6. Select the type as Updategram – click on Next
7. Select Insert operation and from list of tables select EmployeeComp table.
Select both the column names and click on Next and Finish
(EmployeeComp table that we used in the previous session)
8. For the sample BizTalk project, we will use a simple flow
a. Receive message from the file pick up location
b. Send request to the SQL server – AdventureWorks database
c. Receive response back from the SQL server
d. Send response message to the file location
9. Add appropriate Receive and Send shapes.
10. Right click on the Port Surface and select new Configured port and click on Next.
Provide the name as OldSQLPort and click on Next
Select existing port and select “OldSQLAdapter.InsertEmployeeCompPortType”
Select “I will be sending a request and receiving a response” and “Specify later”
Click Next and Finish
11. While in the Orchestration view add 2 messages
InputMessage = Multi-part - OldSQLAdapter.InsertEmployeeCompRequest
OutputMessage = Multi-part - OldSQLAdapter.InsertEmployeeCompResponse
12. For first Receive and Send shape set message = InputMessage
For second Receive and Send shape set message = OutputMessage
13. Add ports for receiving the request from file location and sending the response to file location.
14. Connect appropriate shapes and ports.
15. Deploy the solution.
16. In BizTalk Administration Console add new Static Solicit-Response Send port.
Select type as old SQL adapter.
Select XMLTransmit and XMLReceive for respective pipelines. Click Configure
Provide appropriate connection string for the AdventureWorks database.
Document Target Namespace = http://OldSQLAdapter
Response Document root element = RequestResponse
Save changes for the Send port.
17. Complete the bindings of the orchestration and start the application.
18. Test the solution by submitting an input message.
22
Steps for creating migration helper project
1. Create a new BizTalk project MigrationHelper
2. Add reference to the OldSQLAdapter project or OldSQLAdapter.dll
3. Now add Insert operation metadata for WCF-SQL adapter using Consume Adapter Service.
Right click project – Add – Add Generated Items – Consume Adapter Service – click on Add
Select sqlBinding and click on Configure
Security
Client credential type = Windows
URI Properties
InitialCatalog = AdventureWorks
Server = localhost
Click on OK and then click on Connect
4. From “Select a Category” expand Tables and select [dbo].[EmployeeComp]
5. From “Available Categories and Operations” select “Insert” operation and click on Add and then click on OK
6. Right click project – Add – New Item and select Map files. Give name as MapForOutgoingRequest
7. For Source schema select OldSQLAdapter.InsertEmployeeCompService and click OK:
Select Request as Root node for Source Schema and click on OK.
8. Select destination schema as MigrationHelper.Tableoperation_dbo_EmployeeComp and click OK:
23
Select Insert as Root Node for Target Schema.
9.
10.
11.
12.
Map EmployeeID to EmployeeID and Name to Name
Save and close the map
Right click project – Add – New Item and select Map files. Give name as MapForInComingResponse
For Source schema select MigrationHelper.Tableoperation_dbo_EmployeeComp and click OK. Select
InsertResponse as Root Node for Source Schema
13. For Destination schema select OldSQLAdapter.InsertEmployeeCompService and click OK. Select
RequestResponse as Root Node for Destination Schema.
14. On the map page add Mass Copy functoid. Link “InsertResult” from source schema to the functiod and link
“Success” from Destination Schema to the functiod:
24
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
Save and close the map.
Deploy the MigrationHelper project
Import the binding file for creating WCF-SQL port.
Edit properties for the Send port just created.
For the Send port, change the SOAP action to TableOp/Insert/dbo/EmployeeComp
Select Inbound maps – set map = MapForIncomingResponse
Select Outbound maps – set map = MapForOutgoingRequest
Save the changes and start the send port
Un-enlist the OldSQLAdapter.Orchestration_1 and go to it properties – Bindings
For the logical SQL send port set the value to use new WCF-SQL port
Start the orchestration and test it using an input message.
25
Configuring Dynamic Ports
Until the release of fix KB942465: http://support.microsoft.com/kb/942465 , there were no dynamic ports in the old
SQL adapter.
In BizTalk Server, you can configure dynamic ports for a WCF-Custom / WCF-SQL adapter. Because the SQL adapter is a
WCF-based adapter, you can dynamically configure a port for the SQL adapter by using message context properties.
For the WCF SQL adapter, the URI, action, and binding may be determined from a property on an incoming message,
and then specified in the Expression shape, as shown in the following example:
Request2 = Request1;
Request2(WCF.Action)="TableOp/Insert/dbo/CustomerTable";
Request2(WCF.BindingType) = "sqlBinding";
Request2(WCF.UserName)="myuser";
Request2(WCF.Password)="mypass"; //provide credential if required
SendPort(Microsoft.XLANGs.BaseTypes.TransportType)="WCF-Custom"; //or WCF-SQL
SendPort(Microsoft.XLANGs.BaseTypes.Address)="mssql://sql_server/my_instance/my_database"
;
In the preceding example:
Request2 message is being created from Request1 message. Both messages map to an operation schema, which
is generated using the Add Adapter Metadata/ Consume Adapter Service.
SendPort is the name of the logical send port in the BizTalk orchestration.
Polling for SQL Adapter
In this session we will work on Service Outbound Operations – Polling .
You can configure the SQL adapter to receive polling-based data-changed messages from SQL Server. You can specify a
polling statement that the adapter executes to poll the database. The polling statement can be a SELECT statement or a
stored procedure that returns a result set. Based on the type of polling message received, the adapter exposes different
polling operations:
Polling This operation returns a data set as part of the polling message. At design time, the schema of the database
object being polled is not available. Instead, the schema is available as part of the polling message during run time.
TypedPolling This operation returns a strongly-typed polling message. At design time, the schema of the database object
is also available. You should use this operation for polling if you want to map certain elements from the polling message
to another schema, which could be for another operation.
XmlPolling This operation returns the polling message as an XML message. You should use this operation if you want to
use SELECT statements or stored procedures that use the FOR XML clause to return data as XML messages.
The SQL adapter enables adapter clients to have BizTalk applications with more than one Polling or TypedPolling
operations for the same database or table. To support such a scenario, the adapter includes a unique ID— InboundID—
in the connection URI. Because the connectionURIs become unique by adding the InboundID property, you can now
have multiple receive ports polling the same database or table in a single BizTalk application.
We will work on TypedPolling operation sample to complete the following steps:
26
1. Select all the rows from the EmployeeComp table.
2. Execute a stored procedure [dbo].[MoveEmployee] to move all the records from the EmployeeComp table
to the EmployeeTemp table.
3. Execute a stored procedure [dbo].[AddEmployee] to add a new record to the EmployeeComp table. This will
ensure that after polling interval there will be a record to select.
We need to use following binding properties while working with the Polling operation:
Binding Property
Description
InboundOperationType
Specifies whether you want to perform Polling, TypedPolling, or Notification inbound
operation. Default is Polling.
Specifies the SQL statement that the adapter executes to determine whether any data
is available for polling. The SQL statement must return a result set consisting of rows
PolledDataAvailableStatement
and columns. Only if a row is available, the SQL statement specified for the
PollingStatement binding property will be executed.
PollingIntervalInSeconds
Specifies the interval, in seconds, at which the SQL adapter executes the statement
specified for the PolledDataAvailableStatement binding property. The default is 30
seconds. The polling interval determines the time interval between successive polls. If
the statement is executed within the specified interval, the adapter waits for the
remaining time in the interval.
PollingStatement
Specifies the SQL statement to poll the SQL Server database table. You can specify a
simple SELECT statement or a stored procedure for the polling statement. The default
is null. You must specify a value for PollingStatement to enable polling. The polling
statement is executed only if there is data available for polling, which is determined by
the PolledDataAvailableStatement binding property. You can specify any number of
SQL statements separated by a semi-colon.
PollWhileDataFound
Specifies whether the SQL adapter ignores the polling interval and continuously
executes the SQL statement specified for the PolledDataAvailableStatement binding
property, if data is available in the table being polled. If no data is available in the table,
the adapter reverts to execute the SQL statement at the specified polling interval.
Default is false.
While using simple Polling operation, you may choose to specify these binding properties when generating the schema
for the Polling operation, even though it is not mandatory. If you do so, the port binding file that the Consume Adapter
Service Add-in generates as part of the metadata generation also contains the values you specify for the binding
properties. You can later import this binding file in the BizTalk Server Administration console to create the WCF-custom
or WCF-SQL receive port with the binding properties already set.
For Typed Polling, you have to specify InboundId and PollingStatement property while generating metadata:
1.
2.
3.
4.
Create a new BizTalk project named PollingSample
Right click on the project name – Add – Add Generated Items – Consume Adapter Service and click on Add
Select sqlbinding from the binding list
Click on Configure
a. Security
i. Client credential = Windows
b. URI Properties
i. Intial catalog = AdventureWorks
ii. Server = localhost
27
iii. InboundID = PollingSample
c. Binding Properties
i. InboundOperatoinType = TypedPolling
ii. PolledDataAvailabeStatement = Select count(*) from EmployeeComp
iii. PollingIntervalInSeconds = 60
iv. PollingStatement = Select * from EmployeeComp; EXEC [dbo].[MoveEmployee]
v. PollWhileDataFound = False
Click on Connect.
From "Select contract type" select "Service (Inbound operations)"
From "Select a category" select "/"
From Available categories and operations select "TypedPolling"
Click on Add and then click on OK.
A TypedPolling.PollingSample.xsd and binding files is added to the project.
Add a new schema to the project - name the file as EmpDetails.
Right click on the Root node and select Insert Schema Node - Child field element
Name the field as Detail
Save and close schema.
Add a new map to the project - name the map as MapPolledData
Click "Open Source Schema". Select TypedPolling.PollingSample.xsd and then select "TypedPolling" and click
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
OK.
17. Click "Open Destination Schema". Select EmpDetails and click OK
18. Use String String Concatenate functoid to map EmployeeID and Name to Detail.
19. Use Looping functoid to map TypedPollingResultSet0 to Detail.
20. Save and close the map.
28
21. Add a new orchestration to the project.
22. Add Receive port to receive the message from SQL database. We will specify the port binding later.
23. In the orchestration view, add 2 messages.
a. InputMessage = PollingSample.TypedPolling_PollingSample.TypedPolling
b. OutputMessage = PollingSample.EmpDetails
24. Add a Receive shape, Transform and a Send shape.
25. For receive shapes specify Message = InputMessage
26. For Transform shape set the following properties
a. Input Message = InputMessage
b. Output Message = OutputMessage
c. Map Name = PollingSample.MapPolledData
27. For send shape specify Message = OutputMessage
28. Add a send port to set the output to a file location.
29. Connect Receive and Send shapes to appropriate ports.
30. Compile and deploy the project.
31. Import the binding file to create WCF-SQL receive port.
32. Complete the orchestration binding and start the application.
33. Check the output message.
If required run the AddEmployee stored procedure to add more rows to EmployeeComp table:
Exec [dbo].[AddEmployee] 'NewEmployee'
PollWhileDataFound Property
When the value of the PollWhileDataFound is set to “False” (default setting):
29
When the value of the PollWhileDataFound is set to “True”:
30
Notification for SQL Adapter
In this session we will work on Service (Inbound Operations) - Notification.
The adapter is not designed to distinguish the operation for which notification is being sent. It will simply pass the
notification to the application. It is application’s responsibility to interpret the notification and take the necessary action.
That means, after receiving query notification users should “mandatorily” check operation from the notification message
sent.
Why is it so important?
– Upon getting first notification you perform some action on the data which is being observed for the change
– that triggers another notification
– the application receives the subsequent notification
The loop can become endless if people don’t understand this and don’t design the applications to discard the unwanted
notifications (when the actions are recursive). That implies people need to “understand” about NotifyOnListenerStart
message and what to do with it.
To support query notifications, the adapter clients and the SQL Server database have to fulfill certain requirements. For
detailed information about these requirements, see “Enabling Query Notifications” at
http://go.microsoft.com/fwlink/?LinkID=122323.
From this topic specifically go through SQL BOL links – Query Notifications Requirements – lots of good to know things
for troubleshooting when everything from BizTalk perspective seems all-right but still notifications are not being
received.
The adapter clients can subscribe to receive query notifications about the data changes in the SQL Server database. A
SQL SELECT statement or a stored procedure specifies the data-change criteria in a table for triggering of the query
notifications, and the SQL Server sends query notifications as and when the result set for the SELECT statement or the
stored procedure changes.
Once the adapter clients receive a notification message, they can perform specific tasks based on the kind of notification
received. For example, a BizTalk orchestration can be designed in such a way that it performs one set of tasks if an insert
notification is received and another set of tasks if an update notification is received.
NotifyOnListenerStart
If the receive location on which the adapter clients are receiving notifications goes down, adapter clients can configure
the adapter to receive a notification when receive location comes back up. It is important to understand that there is
no mechanism to cache the notification messages if receive location is down for some reason. It is an event – receive
it or lose it.
If you set the NotifyOnListenerStart = True, then as soon as receive location comes back up, the application will
receive “Listener Started” message. Upon receiving this message, application can immediately check for data
modifications.
If you set NotifyOnListenerStart = False, Listener Started message is not delivered. Subsequent notifications will
come as data under the observation is modified after the receive location comes back up.
We will create a sample to see various notification messages. Make sure you have enabled query notification on the
Adventureworks database by executing:
ALTER DATABASE AdventureWorks SET ENABLE_BROKER;
31
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
Create a new BizTalk project named NotificationSample
Right click on the project name – Add – Add Generated Items – Consume Adapter Service and click on Add
Select sqlbinding from the binding list
Click on Configure
a. Security
i. Client credential = Windows
b. URI Properties
i. Initial catalog = AdventureWorks
ii. Server = localhost
c. Binding Properties
i. InboundOperationType = Notification
ii. NotificationStatement = Select EmployeeID,Name,Status from dbo.EmployeeComp Where
Status = 0
Click on connect.
From “Select Contract Type” select – Service (Inbound operations)
From “Select Category”, select “/”
From “Available categories and operations” select Notification – click on Add and then click on OK
Notice that Notification.xsd is added to the project – have a look at it.
Add an orchestration to the project.
Add receive and send shape.
In the orchestration view create a NotificationMessage of type Notification.
Add configured receive port to receive notification from the SQL server (you will specify the port binding later)
Add a configured send port to dump the notification message to a file location.
Connect respective shapes and deploy the application.
Import the binding file that was created while adding metadata.
Start the File send port – bind the orchestration and start the orchestration
Enable the receive location. As soon as you enable the receive location, you will get a message in the output folder:
<?xml version="1.0" encoding="utf-8" ?>
<Notification xmlns="http://schemas.microsoft.com/Sql/2008/05/Notification/">
<Info>ListenerStarted</Info>
<Source>SqlBinding</Source>
<Type>Startup</Type>
</Notification>
This is what we talked about – Notify On Listener Start message – It is coming because NotifyOnListenerStart is by
default true.
Go to the properties for the receive location and in the binding set NotifyOnListenerStart = False.
Disable and enable the receive location – you won’t get any message.
Let us execute different operation to check various notification messages.
32
Operation
Notification
<Info>Insert</Info>
Insert into EmployeeComp (Name,Status) Values ('John123',0) <Source>Data</Source>
<Type>Change</Type>
Update EmployeeComp Set Name = 'Value' where EmployeeID=1
(make sure this EmployeeID exists)
<Info>Update</Info>
<Source>Data</Source>
<Type>Change</Type>
Delete from EmployeeComp where EmployeeID = 5
(make sure this EmployeeID exists)
<Info>Delete</Info>
<Source>Data</Source>
<Type>Change</Type>
Truncate table EmployeeComp
<Info>Truncate</Info>
<Source>Data</Source>
<Type>Change</Type>
Insert into EmployeeComp (Name,Status) Values ('John123',1) No notification message
Update EmployeeComp Set Status = 1 where EmployeeID=1
(make sure this EmployeeID exists)
No notification message
Notice that the last two operations did not trigger any notification message – that shows the importance of the “where”
clause in the Notification Statement. This is the first filter to eliminate the noise. And by this time as you should have
figured it out that the second filter is <Info>Operation</Info>.
Let us see how to use it within the orchestration:
1. Modify the existing orchestration – after first receive shape add the Expression shape.
2. Create a variable that will contain the value within the <Info> tag and set its type to System.String. Name the
variable as NotificationType.
3. Create an xpath query to extract the value from the <Info> tag and paste it in the expression shape that you
added.
NotificationType = xpath(NotificationMessage,"string(/*[local-name()='Notification']/*[localname()='Info']/text())");
In this xpath query, NotificationMessage is the message you created for receiving notification messages.
4. Add Decide shape just below the Expression shape.
5. For Rule_1 set the condition NotificationType.Equals("Insert")
6. Move the existing Send shape under the Else branch – this will dump out the discarded notifications.
We want to process Insert notification only. For that we will add some logic under the branch Rule_1.
We will find out EmployeeID for the inserted record – we assume that for the newly inserted Employee the
Status will be always 0.
It is important to have some condition associated for the specific operation – otherwise how you are going to
distinguish the data? Mind you – it is just a notification that the underlying data is changed. What has changed?
You go and figure it out.
So we will select an employee record where Status = 0 and we will move the record to the EmployeeTemp table
using the stored procedure [dbo].[DeleteEmployee].
Have look at the script for the stored procedure.
Add the metadata for the TypedProcedure - [dbo].[DeleteEmployee]operation using “Consume Adapter Service”
so that we get a readymade port binding file.
7. While in the orchestration view, add two messages
a. EmployeeSelectRequest = NotificationSample.TypedProcedure_dbo.DeleteEmployee
b. EmployeeSelectResponse = NotificationSample.TypedProcedure_dbo.DeleteEmployeeResponse
8. Add a Construct Message shape under Rule_1 and add Message Assignment Shape within it.
33
The message being constructed is EmployeeSelectRequest – use this message to trigger the stored procedure.
9. Create a variable RequestMessage of type System.Xml.XmlDocument
10. In the Message Assignment Shape put the following lines to pick up the message from the file location directly
and assign it to the request message.
a. RequestMessage.Load("C:\\Samples\\NotificationSample\\Request.xml");
b. EmployeeSelectRequest = RequestMessage;
11. Add a send shape to send this request to the SQL server. Set message type = EmployeeSelectRequest
12. Add a receive shape to receive the response from the SQL server. Set message type = EmployeeSelectResponse
13. Add a request response port for this operation. Select “I will be sending a request and receiving a response” and
“Specify later”
14. Add a send shape to send the response to a file location.
15. Add a send port for this operation.
16. Connect the appropriate shapes and the ports. Deploy the application.
17. Import the SQL Send port binding file.
Set the SOAP action as TypedProcedure/dbo/DeleteEmployee
Complete the orchestration binding and start the application.
18. If you have set NotifyOnListenerStart = True, you will get listener started message.
19. Use AddEmployee stored procedure to insert a record e.g. Exec AddEmployee 'John123'
20. You will get two responses – one showing the EmployeeID for the insert operation and one discarded Delete
notification.
If we have not checked for the notification operation, the Delete notification would have also caused to execute the
stored procedure again and would have fetched empty result set.
This was harmless in our case – but in the real world scenario – we don’t know what could be the consequences.
So this example shows how to avoid extra trip to the database by discarding the unwanted notifications. As mentioned
earlier, you can’t avoid instantiation of the orchestration.
Now you got the idea –
If there is no where clause in the notification statement
If we don’t check for the notification operation
And on top of that if we operate on the data for a recursive action
The end result is amusing.
34
Appendix: SQL Scripts:
USE [AdventureWorks]
GO
/****** Object: Table [dbo].[EmployeeComp]
******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[EmployeeComp](
[EmployeeID] [int] IDENTITY(1,1) NOT NULL,
[Name] [nvarchar](15) NOT NULL,
[Status] [int] NULL,
CONSTRAINT [PK_EmployeeComp_EmployeeID] PRIMARY KEY NONCLUSTERED
(
[EmployeeID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS
ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
USE [AdventureWorks]
GO
/****** Object: Table [dbo].[EmployeeTemp]
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[EmployeeTemp](
[EmployeeID] [int] NOT NULL,
[Name] [nvarchar](15) NOT NULL,
[Status] [int] NULL
=
******/
) ON [PRIMARY]
USE [AdventureWorks]
GO
/****** Object: StoredProcedure [dbo].[AddEmployee]
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
******/
CREATE PROCEDURE [dbo].[AddEmployee]
@EmpName nvarchar(15)
AS
BEGIN
SET NOCOUNT ON;
Insert into [dbo].[EmployeeComp] (Name,Status) Values (@EmpName,0)
END;
USE [AdventureWorks]
GO
/****** Object: StoredProcedure [dbo].[DeleteEmployee]
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
******/
CREATE PROCEDURE [dbo].[DeleteEmployee]
AS
35
BEGIN
SET NOCOUNT ON;
DECLARE @var int
SELECT TOP 1 @var = EmployeeID FROM EmployeeComp
Insert into [dbo].[EmployeeTemp]
SELECT * FROM [dbo].[EmployeeComp] WHERE EmployeeID=@var
DELETE FROM [dbo].[EmployeeComp] WHERE EmployeeID=@var;
Select @var AS EmployeeID;
END;
USE [AdventureWorks]
GO
/****** Object: StoredProcedure [dbo].[MoveEmployee]
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
******/
CREATE PROCEDURE [dbo].[MoveEmployee]
AS
BEGIN
SET NOCOUNT ON;
Insert into [dbo].[EmployeeTemp]
Select * from [dbo].[EmployeeComp] ;
Delete from [dbo].[EmployeeComp];
END;
36
© Copyright 2026 Paperzz