February 27, 2013 at 3:37 PM

One of the most asked change requests seems to be changing a part of a schema accompanying the modification of a mapping. Since a mapping from BizTalk can be made in the BizTalk mapper or in XSLT, it is always a bit of a surprise, how difficult this can be. It is interesting how the translation of The BizTalk mapper is done under the hood and how we can improve the performance. In this article I will concentrate  on the cumulative concatenate functoid found when working with the BizTalk mapper.

 

Project sample

An external schema contains a report about orders that have been processed. Each order line contains a validation code.
In our internal schema, we would like to use one node to know if the whole order has been processed or not. We can solve this by using the looper functoid, but in this case I will use the Cumulative concatenate functoid. 

 

The BizTalk mapper 

First we cumulate all the status values using a cumulative concatenate, afterwards, a find functoid will tell us if there is a status "NOK" (not ok) is present. Then we will determinate depending on the index if the status will end up in a true or false. This is a piece of cake.
 

 

 

The change

The change regarding this mapping, which should now be extended, the external schema can now have multiple statuses that tell us if a line has not been processed. ("NOK","NIS", "NA").  I won't implement this change, but I will concentrate in how to keep this mapping clean. 

 

Using an external xslt file

I will use an external XSLT schema for applying this change. It seems to be that if we will use another few functoids, our mapping will become a big mess. I simply generated an XSLT  from the existing mapping by right clicking the map in the solution explorer and selecting "Validate map". BizTalk will output two links, one of them will be the XSLT file. Save this file to disk and and refer from the mapping property "Custom XSLT Path" to the external XSLT file.


The first thing that strikes me is the fact that this XSLT file is nearly unreadable, or at least difficult to understand.

Under the hood, BizTalk is using at least one variable for each functoid you use. Since we cannot change the values of a variable in XSLT , BizTalk uses a script block with inline c# code at the bottom of the document for cumulating each value of the node Status.

 

 This is the generated code for the IsValid node. 

 

<xsl:variable name="var:v1"
select="userCSharp:InitCumulativeConcat(0)" /> 

Initialize the Cumulative array: The 0 refers to the fact that this is the first cumulative concatenation we are using in our mapping. This is the Key for our cumulative concatenation function. On that way, we are able to reuse the c# code multiple times again.

     

<xsl:for-each select="/s0:ExtOrderReport/Lines/Line">
        <xsl:variable name="var:v2" select="userCSharp:AddToCumulativeConcat(0,string(Status/text()),'1000')" />
</xsl:for-each>

Loop for each node we would like to concatenate, and give the value to the function "AddToCumulativeConcat". Note that we also use the 0 here.

      

<xsl:variable name="var:v3" select="userCSharp:GetCumulativeConcat(0)" />

Ask to the c# code to get all our values (again with the key 0)

    

<xsl:variable name="var:v4" select="userCSharp:StringFind(string($var:v3) , 'NOK')" />

Find a "NOK" value and returns an index result.
 

<xsl:variable name="var:v5" select="userCSharp:IsValidOrder(string($var:v4))" />
<IsValid>
	<xsl:value-of select="$var:v5" />
</IsValid>

Call our internal c# code to decide if this order is valid or not. 

 

Optimalizations

This seems to be a lot of code, for such a piece of logic, isn't it?

We might could manual optimize this, for performance reasons: 

 

<xsl:variable name="var:v1" select="userCSharp:InitCumulativeConcat(0)" />    
  <xsl:for-each select="/s0:ExtOrderReport/Lines/Line/Status"> 
      <xsl:variable name="var:v2" select="userCSharp:AddToCumulativeConcat(0,string(text()),'1000')" />   
   </xsl:for-each> 
     <xsl:variable name="var:v3" select="userCSharp:GetCumulativeConcat(0)" />    
  <IsValid>       
 <xsl:value-of select="not(contains($var:v3,'NOK'))" />  
    </IsValid>

 

I limited the for-each function only to the node we need, in that way, we only need to loop this node, not the whole line node.

I replaced the c# search function by the build in XSLT search function, since built-in functions are always faster than loading custom c# code.

After that, I limited the variables were possible. 

 

XML profiling

After this manually intervention, I would like to know what the result is of my improvements.

 

Visual studio offers by default XML profiling. When comparing these results, I could say that we did an improvement of nearly 50%

 

  

Conclusions

For long term maintenance reasons it is smarter to write your own xslt, and not use the built-in BTM (BizTalk mapper).

It's always possible to convert convert a BTM to an XSLT.

The BTM might be fast for easy mappings, but even for this, BTM will always generate a less readable and less performance XSLT file.

You can manually improve the mapping speed by yourself.


February 13, 2013 at 4:00 PM

At one of our customers we faced an issue with a large BizTalk DTA database. To get the growth under control, an investigation was launched to see where we tracked message context and bodies. As everyone probably knows, you can enable tracking on send ports, receive ports, pipelines and orchestrations.

Whilst doing some background research I found this interesting tool, the BizTalk tracking exporting and importing utilities from Rudolf Henning. It's hosted on codeplex so you could even consider accessing the source code an tweaking it to your needs but to be honest I found it useful "out of the box".

BTSGetTrackingOptions.exe

The main use of the first tool "BTSGetTrackingOptions.exe" is to call it as a command line utility with the parameters server (name of database server) and database (biztalk management database name), optionally which application (otherwise all), and even if required specific receive or send port, orchestration or pipeline. The tool will dump the result in the XML file of which you specify the name in the parameters. Any tracking reported will be as an "add" key so you can simply use these to import.

BTSGetTrackingOptions.exe outputfilename.xml -srv:databaseservername -db:BizTalkManagementDatabaseName -a:OptionalApplicationName -r:optionalReceivePortName /s:optionalSendPortName -o:OptionOrchestrationName -p:optionalPipelineName

BTSSetTrackingOptions.exe

The second tool "BTSSetTrackingOptions.exe" is, obviously, for importing an XML file. You can choose to add tracking or remove it and which sort of tracking (depending on the name of the key). As the application, send / receive port, orchestration or pipeline names are defined in the XML you import, there is less need to set options on this tool.

BTSSetTrackingOptions.exe importfilename.xml -s:databaseservername -d:BizTalkManagementDatabaseName

I found this tool lightened my work a lot - both in analyzing the tracking settings and in resetting them.
I even made some command files which call specific XML files so we can easily switch between full tracking and reduced tracking.

 

Below: a sample of an XML file describing the tracking settings.

 

Anyone else has some tools for managing BizTalk tracking?


February 6, 2013 at 4:09 PM

When trying to install SQL Server 2008 R2 on a Windows Server 2008 R2 Virtual Machine on Azure, you might come across the following error at the Setup Support Rules step:

 

 

This has to do with two manifest files that are corrupt.

If you have another working installation, you can copy the following two manifest files from the working server to the failing server:

  • C:\Windows\winsxs\Manifests\amd64_microsoft.vc80.atl_1fc8b3b9a1e18e3b_8.0.50727.4053_none_8a1a02152edb659b.manifest
  • C:\Windows\winsxs\Manifests\x86_microsoft.vc80.atl_1fc8b3b9a1e18e3b_8.0.50727.4053_none_d1c738ec43578ea1.manifest

 

If you don’t have another working installation, find and open the files mentioned above and paste the following xml in them:

  • AMD64 Manifest:
    <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
    <!-- Copyright © 1981-2001 Microsoft Corporation -->
    <assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
    <noInheritable/>
    <assemblyIdentity type="win32" name="Microsoft.VC80.ATL" version="8.0.50727.4053" processorArchitecture="amd64" publicKeyToken="1fc8b3b9a1e18e3b"/>
    <file name="ATL80.dll" hash="99840dcc34e78af239d80841eba316c184e407cd" hashalg="SHA1"/>
    </assembly>
  • X86 Manifest:
    <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
    <!-- Copyright © 1981-2001 Microsoft Corporation –>
    <assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
    <noInheritable/>
    <assemblyIdentity type="win32" name="Microsoft.VC80.ATL" version="8.0.50727.4053" processorArchitecture="x86" publicKeyToken="1fc8b3b9a1e18e3b"/>
    <file name="ATL80.dll" hash="6d7ce37b5753aa3f8b6c2c8170011b000bbed2e9" hashalg="SHA1"/>
    </assembly>

 

Note: You probably need to change the permissions for those files to be able to overwrite them.
To do so, go to the file properties, Security tab, Advanced, Owner tab, Edit, Select the Administrators group and click three times OK until all windows are closed.
Reopen the properties for the file, Security tab, Edit, Select the Administrators group and select Full Control.