Stuart Brierley

Integration Management - BizTalk and More

  Home  |   Contact  |   Syndication    |   Login
  65 Posts | 0 Stories | 48 Comments | 0 Trackbacks

News

Archives

Post Categories

Friday, November 04, 2011 #

If you want to debug your custom pipeline component you can make use of the Pipeline.exe utility to do this:

  • Set the breakpoint in your Custom Pipeline Component code in Visual Studio.
  • On the properties page of the project containing your Custom Pipeline select the Debug tab.
  • Set the “Start Action” property to "Start external program" and then type or browse to:

{Installation Location}\Microsoft BizTalk Server 2010\SDK\Utilities\PipelineTools\Pipeline.exe

  • For the "Start Options > Command line arguments" property type:

{PipelinePath}\{PipelineName}.btp -d {MessageInstancePath}\{MessageInstanceName}.xml -c

  • Now, just press F5.  The chosen pipeline will be run and the breakpoint in your Custom Pipeline Component code should be hit, allowing you to step through and debug your code.

As far as I am aware your Custom Pipeline Component and your Custom Pipeline must be in the same solution, although they can of course be in seperate projects.

Note: Pipeline.exe will not execute properly if your Custom Pipeline is using the Flat File Assembler / Disassembler Pipeline Components.  In such cases you will need to create a test Pipeline that excludes these pipeline components. 

  • Share This Post:
  • Share on Twitter
  • Share on Facebook
  • Share on Technorati

Wednesday, October 19, 2011 #

BizTalk Server 2010 - Using the WCF-SQL adapter to make multiple stored procedure calls

A recent project that I was working on required that I take an incoming flat file, containing multiple transaction records, and load these transactions into a database.

Within the source file were multiple instances of any of seven transaction types.  The database had a separate table for each transaction type, each with its own stored procedure for inserting a record.  So thats seven transaction types and seven stored procedures.

Thiago Almeida posted in 2009 on Using the BizTalk WCF-SQL Adapter to load a flat file into a SQL Server 2008 table, where he demonstrated two methods for calling a single stored procedure multiple times:

  • Debatching - splitting the source message into separate messages and loading them individually with the WCF-SQL Adapter
  • Single file - not splitting the source message, sending one single message to the WCF-SQL Adapter

In this posting he was able to show that:

"....the single file method performs much faster for loading the 504 rows into the table. By placing a datetime column on the products table I could see the difference from the first insert to the last is only 254 milliseconds. With the debatch method BizTalk goes through the debatched records at a much slower pace  taking around 16 seconds to load them all, since it has to map each debatched message, route multiple messages to the send port, create multiple transactions against SQL Server, etc."

Given the improved performance of the single file approach, I wondered if this approach could be built on to call all seven of my target stored procedure in a single transaction.  Detailed below is a simplified example of how to call multiple stored procedures in a single transaction.

The Source Schema

The Stored Procedures

Creating the WCF-SQL Schema

First you need to add the SQL Server schemas used by the WCF-SQL Adapter. In Visual Studio, right click on the BizTalk project, select Add, and then ‘Add Generated Items’.

From there you can either choose the "Add Adapter Metadata" or the "Consume Adapter Service" options.  Ultimately both options will lead you to the Consume Adapter Service’ wizard, but selecting "Add Adapter Metadata" will first present you with the Add Adapter Wizard, where you should select WCF-SQL; doing this will pre-fill the binding option in the Consume adapter Service wizard which you would otherwise have to select yourself! 

Selecting "Consume Adapter Service" will open the Consume Adapter Service wizard where you can connect to the target SQL Server database and select what items and operations you want to consume.

You will then need to carry out the following steps:

  • Configure the URI of the target database, using the form "mssql://ServerName:port/InstanceName/Databasename". 
    • In my case I am looking at a local database with only the default instance,  so I put "." as the database name and no instance name.
  • Select Connect.
  • You should then see a list of outbound operations in the Select a Category area.  Select Procedures.
  • You should then see the stored procedures in the Available Categories and operations.
  • Select all stored procedures and press Add.
  • If required check the generate unique schema types checkbox and enter a Filename Prefix.
  • Select OK.

This results in the following schema:

Although this has created a schema containing nodes for each of stored procedure requests (and their respective responses) all are at the root level and therefore only once instance of one of these nodes can exist in the XML instances for this schema.

Creating the Request, RequestResponse message

To create a schema that allows us to make multiple calls to multiple stored procedures, we need to make use of the WCF-SQL Adapter’s composite operations.

You will need to create a new schema with two root nodes, 'Request' and 'RequestResponse'; the name of the request node isn’t really important as long as the corresponding response node name is the same as the first with a ‘Respose’ suffix.

You then need to add the generated schema from earlier as an XSD Import to this new composite schema. 

Under the ‘Request’ node create an unbounded record for each of the stored procedure you want to call, changing each to have the appropriate request data structure from the imported generated schema.

Under the 'Response' node create an unbounded record for each of the stored procedure you want to call, changing each to have the appropriate response data structure from the imported generated schema.
 

Map Source to Request

This allows us to map from the source schema to our multiple procedure call schema.  When adding the destination schema you will be prompted to select the root node.  In this case select Request, if you need to map from the response at a later date you should obviously select RequestResponse instead:

For each instance of a Return, Sale or SpoiltStock record in the source message, the following map will result in a corresponding stored procedure request in the destination message.

For example, using the source message:

Results in the destination message:

WCF-Custom Adapter Send Port Configuration

After deploying the solution and creating an appropriate receive port and location for the source message, you will need to create a send port using the WCF-Custom Adapter and the sqlBinding.


Set the address URI to you target database, and the Soap Action Header to "CompositeOperation":
 

Set the Binding Type to "sqlBinding" and use the default values, making sure that "useAmbientTransaction" is enabled.  This ensures that the multiple stored procedure calls are inside a single transaction:

When you submit your request message it should now be mapped into a single request containing multiple stored procedure calls, which will hit the target database in a highly efficient single transaction. 

For the live example I cited earlier (seven transaction types with seven different possible stored procedures) each night this approach is being used to process around 15,000 stored procedure calls in a single transaction.  So far it has proven to be robust and reliable, taking less than a minute to complete this call.
 

 

  • Share This Post:
  • Share on Twitter
  • Share on Facebook
  • Share on Technorati

Friday, September 09, 2011 #

The following error was encountered when consuming a flat file through a pipeline that made use of the Flat File Disassembler pipeline component:

There was a failure executing the receive pipeline: "xxxxxxxxx, xxxxxxxx, Version=1.0.0.0, Culture=neutral, PublicKeyToken=xxxxxxx" Source: "Flat file disassembler" Receive Port: "xxxxxxxxx" URI: "C:\BizTalk Folders\xxxxxxxxx\*.csv" Reason: Cannot access a disposed object. Object name: 'DataReader'.

This was resolved by settling 'RecoverableInterchangeProcessing' to True in the Receive Pipeline Properties on the Receive Location.

 

  • Share This Post:
  • Share on Twitter
  • Share on Facebook
  • Share on Technorati

While undeploying a BizTalk Applciation recently something went wrong, leaving BizTalk in a strange state.

When opening the BizTalk Server Administration Console the following message would be displayed:

Schema referenced by Map 'xxxxxxx' has been deleted. The local, cached version of the BizTalk Server group configuration is out of date. You must refresh the BizTalk Server group configuration before making further changes.

The problem with this was that any attempt to refresh the BizTalk group in the console failed.

I also tried such things as service and server restarts but nothing so simple worked. 

Following various leads lead me to look at the bt_mapspec table in the BizTalkMgmtDb database.  Here I saw that, although the application and all other artifacts of the application had been removed, there was still an entry for the map that the error was reporting on.

Deleting this entry allowed the group to be refreshed and the undeployment and deployment of updated applications have since been working without any problems.

DELETE FROM bt_mapspec WHERE itemid = xxx

 

  • Share This Post:
  • Share on Twitter
  • Share on Facebook
  • Share on Technorati

Monday, June 06, 2011 #

This morning I was reading through some of my usual blogs and came across some very interesting and updated information relating to BizTalk performance and hyper-threading.  The two source pages are:

http://appfabriccat.com/2011/05/intel-hyper-threading-redux-for-biztalk-and-app-servers-this-is-not-your-fathers-hyper-threading/

http://msdn.microsoft.com/en-us/library/ee377075(BTS.70).aspx

If you take a look at these pages, you can see that the recommendations on hyper-threading and the BizTalk platform  have changed completely; from explicitly stating that it should be disabled in BIOS to recommending that you enable this on newer processors:

“In the past, we have always recommended disabling Intel’s Hyper-Threading in the server’s BIOS on your BizTalk Server and SQL Server machines (for processors that are Hyper-Threading enabled).”

Pre-Nehalem Hyper-Threading:
• It is critical that hyper-threading be turned off on BizTalk Server computers. This is a BIOS setting, typically found in the Processor settings of the BIOS setup. Hyper-threading makes the server appear to have more processors/processor cores than it actually does; however, hyper-threaded processors typically provide between 20-30% of the performance of a physical processor/processor core. When BizTalk Server counts the number of processors to adjust its self-tuning algorithms, the hyper-threaded processors cause these adjustments to be skewed, which is detrimental to overall performance.
• Hyper-threading should be turned off on SQL Server computers because applications that can cause high levels of contention (such as BizTalk Server) may cause decreased performance in a hyper-threaded environment on a SQL Server computer.


Nehalem Hyper-Threading:
• Unlike in older architectures, enabling hyper-threading in Intel microarchitecture “Nehalem” processors can provide up to an almost linear capacity increase. For the best performance results, when you deploy “Nehalem” processors, we recommend that you configure the computer’s BIOS by enabling Intel Hyper-Threading (H-T) Technology for a marked increase in throughput.”

Impressively, it seems that the modern implementation of hyper-threading means that you can get the same performance out of a reduced number of BizTalk servers:

“With Intel’s latest Xeon processors coming with 8 or 10 physical cores (which would be 16 or 20 logical cores with HT enabled), the performance results for even a single machine can be very impressive. With the latest hardware, latest Windows (2008 R2), latest SQL Server (2008 R2), and BizTalk Server 2010, we basically matched the performance from the BizTalk Server 2009 Performance Optimization Guide, while needing only half as many BizTalk Servers to reach the same results.”

For full details of the tests carried out and the updated performance guidance, give the links above a thorough read.

 

 

  • Share This Post:
  • Share on Twitter
  • Share on Facebook
  • Share on Technorati

Monday, May 09, 2011 #

I was recently installing BizTalk Server 2010 and encountered an error that I had not seen before:

Error 5009 Registration of BAM performance counters failed

After a small amount of investigation it turn out to be a known issue where the performance counter registry has been damaged.

To fix this problem open a command prompt as administrator and run:

lodctr /r

This will rebuild the performance counter registry, after which you should be able to successfully install BizTalk Server. 

  • Share This Post:
  • Share on Twitter
  • Share on Facebook
  • Share on Technorati

Thursday, April 14, 2011 #

I was recently installing a new BizTalk Server 2010 mult-server implementation, where the SQL server installation resides on a separate server to the BizTalk server installation(s) and I ran into a problem when attempting to configure the first server in the BizTalk Group.

I was able to succesfully set up the configuration, but when applying the configuration the tool was unable to create the BizTalk Group.

The SSO set up completed successfully, and looking at the SQL server a number of BizTalk Databases and SQL Server Agent jobs were created, but the BizTalk Group itself was not.

It turns out that this was an issue with the installation of MSDTC on the servers in question.

I diagnosed this by using the dtcping tool.  Although this tool succeeded, it did warn me that the CID values on the two servers were the same.  Investigating further, they were actually the same on the two BizTalk servers, the SQL server and the SharePoint server we were planning to use.

These duplicate values were causing the problem with the creation of the BizTalk Group, and were caused by the same Windows Server 2008 R2 image being used to create the base system for each server in VM Ware.

To check and correct the CID values, carry out the following process on each server: 

  1. Click Start, click Run, type regedit and then click OK to open the registry editor.

  1. Navigate to Hkey_classes_root, CID.

  1. Compare the values of the GUIDs beneath CID on the various servers.
  1. If any of the servers have matching values:
    1. Click start and then run the command prompt as Administrator
    2. Uninstall msdtc by typing: msdtc –uninstall
    3. Install msdtc by typing: msdtc –install
    4. This must be done on all servers with duplicate values.
  1. The CID registry keys should now be unique across the servers involved.

Following this you will need to clean up the partially created BizTalk databases and unconfigure SSO. 

You should then be able to complete the BizTalk configuration successfully.

  • Share This Post:
  • Share on Twitter
  • Share on Facebook
  • Share on Technorati

Monday, March 07, 2011 #

Just released to Codeplex is an updated version of my archiving pipeline component for BizTalk.

The changes in this release are:
  • Addition of FTP adapter macros to the base macros and File adapter macros.
  • Fix for the issue of garbage collection of data streams within pipelines as discussed in this previous blog entry.
  • Now looks for OutboundTransportType in addition to InboundTransportType to pick up send port transport type; Therefore changed %InboundTransportType% macro to %TransportType%.

An initial outline of the project can be read here.

  • Share This Post:
  • Share on Twitter
  • Share on Facebook
  • Share on Technorati

Thursday, March 03, 2011 #

Yesterday I posted about my BizTalk Archiving Pipeline Component, which can be found on Codeplex if anyone is interested in taking a look.

During testing of this component I began to encounter an error whereby the component would throw an "Object reference not set to an instance of an object" error when processing as a part of a Custom Pipeline.

This was occurring when the component was reading a ReadOnlySeekableStream so that the data can be archived to file, but the actual code throwing the error was somewhere in the depths of the Microsoft.BizTalk.Streaming stack.

It turns out that there is a known issue where this exception can be thrown because the garbage collector has disposed of of the stream before execution of the custom pipeline has completed.

To get around this you need to add the streams in your code to the pipeline context resource tracker.
 

So a block of my code goes from:

                        originalStrm = bodyPart.GetOriginalDataStream();

                        if (!originalStrm.CanSeek)
                        {
                            ReadOnlySeekableStream seekableStream = new ReadOnlySeekableStream(originalStrm);
                            inmsg.BodyPart.Data = seekableStream;
                            originalStrm = inmsg.BodyPart.Data;
                        }

                        fileArchive = new FileStream(FullPath, FileMode.Create, FileAccess.Write);
                        binWriter = new BinaryWriter(fileArchive);
                        byte[] buffer = new byte[bufferSize];
                        int sizeRead = 0;

                        while ((sizeRead = originalStrm.Read(buffer, 0, bufferSize)) != 0)
                        {
                            binWriter.Write(buffer, 0, sizeRead);
                        }

to

                        originalStrm = bodyPart.GetOriginalDataStream();

                        if (!originalStrm.CanSeek)
                        {
                            ReadOnlySeekableStream seekableStream = new ReadOnlySeekableStream(originalStrm);
                            inmsg.BodyPart.Data = seekableStream;
                            originalStrm = inmsg.BodyPart.Data;
                        }

                        pc.ResourceTracker.AddResource(originalStrm);

                        fileArchive = new FileStream(FullPath, FileMode.Create, FileAccess.Write);
                        binWriter = new BinaryWriter(fileArchive);
                        byte[] buffer = new byte[bufferSize];
                        int sizeRead = 0;

                        while ((sizeRead = originalStrm.Read(buffer, 0, bufferSize)) != 0)
                        {
                            binWriter.Write(buffer, 0, sizeRead);
                        }

So far this seems to have solved the issue, the error is no more, and my archive component is continuing its way through testing.

 

  • Share This Post:
  • Share on Twitter
  • Share on Facebook
  • Share on Technorati

Wednesday, March 02, 2011 #

In an effort to give a little more to the BizTalk development community, I have created my first Codeplex project.

The SAB BizTalk Archiving Pipeline Component was written using Visual Studio 2010 with BizTalk Server 2010 intended as the target platform.  It is currently at version 0.1, meaning that I have not yet completed all the intended functionality and have so far carried out a limited number of tests.  It does however archive files within the bounds of the functionailty so far implemented and seems to be stable in use.

It is based on a recent evolution of a basic archiving component that I wrote in the past, and it is my hope that it will continue to evolve in the coming months.

This work was inspired by some old posts by Gilles Zunino and Jeff Lynch.  

You can download the documentation, source code or component dll from Codeplex, but to give you a taste here is the first section of the documentation to whet your appetite:

SAB BizTalk Archiving Pipeline Component
 
The SAB BizTalk Archiving Pipeline Component has been developed to allow custom piplelines to be created that can archive messages at any stage of pipeline processing.
 
It works in both receive and send pipelines and will archive messages to file based on the configuration applied to the component in the BizTalk Administration Console.
 
The Archiving Pipeline Component has been coded for use with BizTalk Server 2010. Use with other versions of BizTalk has not been tested.
 
The Archiving Pipeline component is supplied as a dll file that should be placed in the BizTalk Server Pipeline Components folder. It can then be used when developing custom pipelines to be deployed as a part of your BizTalk Server applications.
 
This version of the component allows you to use a number of generic messaging macros and also a small number that are specific to the FILE adapter. It is intended to extend these macros to cover context properties from other adapters in future releases.
 
 
Archive Pipeline Parameters
As with all pipeline components, the following parameters can be set when creating your custom pipeline and at runtime via the administration console.
 
Enabled:              Enables and disables the archive process.
 
                              True; messages will be archived.
 
False; messages will be passed to the next stage in the pipeline without performing any processing.
 
File Name:          The file name of the archived message.
 
Allows the component to build the archive filename at run-time; based on the values entered, the permitted macros and data extracted from the message context properties.
 
e.g.        %FileReceivedFileName%-%InterchangeSequenceNumber%
 
File Mask:           The extension to be added to the File Name following all Macro processing.
 
e.g.        .xml
 
File Path:             The path on which the archived message should be saved.
 
Allows the component to build the archive directory at run-time; based on the values entered, permitted macros and data extracted from the message context properties.
 
e.g.        C:\Archive\%ReceivePortName%\%Year%\%Month%\%Day%\
 
                \\ArchiveShare\%ReceivePortName%\%Date%\
 
 
Overwrite:          Enables and disables existing file overwrites.
 
True; any existing file with the same File Path/Name combination (following macro replacement) will be overwritten.
 
False; any existing file with the same File Path/Name combination (following macro replacement) will not be overwritten.  The current message will be archived with a GUID appended to the File Name.
              
  • Share This Post:
  • Share on Twitter
  • Share on Facebook
  • Share on Technorati