Connected Thoughts – Thiago Almeida

September 9, 2008

Multiple Stored Procedure Calls using the BizTalk SQL Adapter without a loop shape

Filed under: BizTalk — Tags: , , , — Thiago Almeida @ 4:23 pm

Alright, now that the New Zealand Tech Ed is done and dusted people around here are back at blogging, including me.

I thought I’d start with one that’s been on my list for a while: how to make multiple calls to the same stored procedure using the SQL Adapter without having to use a loop shape.

No matter how much you use BizTalk – you’re always learning a new trick. This one comes courtesy of some fellow BizTalk developers here at work – Mark Brimble, Capree Lim and Colin Dijkgraaf.

Say I have this table inside my SQL Server MyTestDB database: 

CREATE TABLE [dbo].[tbMyTestTable]  

([id] [int] IDENTITY(1,1) NOT NULL,

[Code] [nchar] (5) NOT NULL,
[Name] [nchar] (30) NOT NULL,
 [Type] [nchar] (10) NOT NULL,
[PartnerID] [int] NOT NULL,  

CONSTRAINT [PK_tbMyTestTable] PRIMARY KEY CLUSTERED 
([id] ASC) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]) ON [PRIMARY]

 And I have this stored procedure on the same database:

CREATE
PROCEDURE [dbo].[myTestSProc]

    @Code nchar(5) ,@Name nchar(30), @Type nchar(10), @PartnerID int

AS BEGIN

    SET NOCOUNT ON;

    IF EXISTS(Select Code from tbMyTestTable tb where Code= @Code)

        UPDATE [MyTestDB].[dbo].[tbMyTestTable]

         SET [Code] = @Code, [Name] = @Name, [Type] = @Type, [PartnerID] = @PartnerID

         WHERE [Code] = @Code

    ELSE

        INSERT INTO [MyTestDB].[dbo].[tbMyTestTable]

            ([Code], [Name], [Type], [PartnerID])

        VALUES (@Code, @Name, @Type, @PartnerID)

END

 As you can see, the stored procedure will insert a new row in case the code doesn’t already exist, otherwise it will update the row with that code. From this I used the trusty “Add Generated Items” -> “Add Adapter Metadata” to create the schema for that stored procedure. It looks like this:


Now, here is the trick: on the properties of the myTestSProc node (the node with the name of your stored procedure) I changed the Max Occurs setting to unbounded. This will make the schema allow us to repeat that row of XML as many times as we want.

I then created a flat file schema with those same elements:


And, of course, a straight map between the two:


 

And for simplicity I created an orchestration to manage it all (although it could and should all have been done via messaging with no need for an orchestration):

 


Notice how there is no looping shape in the orchestration – it is doing a straight map. So if my (weird) test flat file looks like:

AAA,First Code,Blue,1

AAB,Second Code,Blue,2

AAC,Third Code,Blue,3

AAD,Fourth Code,Green,4

AAE,Fifth Code,Red,5

AAF,Sixth Code,Green,6

AAG,Seventh Code,Green,7

AAH,Eight Code,Red,8

AAI,Ninth Code,Yellow,9

AAA,Tenth Code,Green,10

 

It gets mapped to the following XML which is then sent to the SQL Adapter:

<ns0:SQLInsertCodeReq
xmlns:ns0=http://MyBizTalkProject/SQLInsert>

    <ns0:myTestSProc Code=AAAName=First CodeType=BluePartnerID=1></ns0:myTestSProc>

    <ns0:myTestSProc Code=AABName=Second CodeType=BluePartnerID=2></ns0:myTestSProc>

    <ns0:myTestSProc Code=AACName=Third CodeType=BluePartnerID=3></ns0:myTestSProc>

    <ns0:myTestSProc Code=AADName=Fourth CodeType=GreenPartnerID=4></ns0:myTestSProc>

    <ns0:myTestSProc Code=AAEName=Fifth CodeType=RedPartnerID=5></ns0:myTestSProc>

    <ns0:myTestSProc Code=AAFName=Sixth CodeType=GreenPartnerID=6></ns0:myTestSProc>

    <ns0:myTestSProc Code=AAGName=Seventh CodeType=GreenPartnerID=7></ns0:myTestSProc>

    <ns0:myTestSProc Code=AAHName=Eight CodeType=RedPartnerID=8></ns0:myTestSProc>

    <ns0:myTestSProc Code=AAIName=Ninth CodeType=YellowPartnerID=9></ns0:myTestSProc>

    <ns0:myTestSProc Code=AAAName=Tenth CodeType=GreenPartnerID=10></ns0:myTestSProc>

</ns0:SQLInsertCodeReq>

So after configuring all the ports and binding everything as per normal SQL Adapter, we end up with nine rows in the table. Nine rows? Hah! Notice that the code on the last line is ‘AAA’, so the stored procedure just updates the row that was inserted first.

This is pretty powerful: all the calls to the stored procedure get wrapped around the same DTC transaction. If one of them fails (which I tested by changing a PartnerID to a string) the whole thing gets rolled back. We have something similar in production uploading a file with 30 thousand records in less than a minute as well.

DOWNLOAD THE SAMPLE CODE

Hope it’s useful to other BizTalkers.
–Thiago Almeida

22 Comments »

  1. Good Trick Thiago!

    Comment by Nino Crudele — September 9, 2008 @ 7:13 pm

  2. damn … that’s most definitely useful info. will make sure to make use of this in future.

    Comment by Ryan CrawCour — September 9, 2008 @ 10:49 pm

  3. For extra bonus points, let’s see your compensation routine for this! :)

    Comment by Lucas Vogel — September 10, 2008 @ 1:32 am

  4. This is so damn easy it makes me cry that I did not figure this out sooner! This is a huge performance boost for some of my solutions!!!

    Comment by Ben — September 10, 2008 @ 2:20 am

  5. Oh, and thanks for posting this!

    Comment by Ben — September 10, 2008 @ 2:20 am

  6. Thanks all! One thing I forgot to mention is that this will not work if your stored procedure is returning XML back to the orchestration. The new “WCF LOB Adapter SDK”-based SQL Adapter will allow that.

    Comment by Thiago Almeida — September 10, 2008 @ 8:33 am

    • Hi Thiago,

      Please send me the sample running for this application. As I am pretty new in Biztalk so not able to understand this. Although I tried to make the application like this but its just fetching the first row only and passing the same to database. But its not transferring the other rows.

      Please help me and send me the sample. It is too urgent to save my job.

      Regards.
      Rimps

      Comment by Rimps — August 7, 2009 @ 4:38 pm

  7. Nice trick, I tried it out on my BizTalk 2006 R2 VPC and worked like a charm.

    Comment by Steef-Jan — September 12, 2008 @ 6:39 am

  8. Excellent tip.. it will certainly boost performance…

    Comment by Marshal — September 14, 2008 @ 3:12 am

  9. [...] Finally if you are de-batching just so you can submit your messages to a SQL send port one by one don’t bother. See this article by Multiple Stored Procedure Calls using the BizTalk SQL Adapter without a loop shape « Connected Thou… [...]

    Pingback by Tricks with Schemas Part 1: De-batching from a SQL Receive Port « Connected Pawns — September 25, 2008 @ 1:18 pm

  10. Hi all!
    Nice site!

    Bye

    Comment by oblilaitatips — October 2, 2008 @ 1:59 am

  11. Hi Thiago Almeida! Do you know something about this in Oracle Adapter? Can be done? Because we have something like this in the Metadata generated Schema:

    (…)

    So… as the first element cannot be multiple, I guess there is no other option than the loop.

    Best regards and congrats for the BizTalk/SQL tip ;-)

    Daniel Santana

    Comment by Daniel Santana — December 9, 2008 @ 9:08 am

  12. Hummmm…. problem with the posted schema… Lets try again…

    [?xml version="1.0"?]
    [xsd:schema xmlns:PKG_ATRIBUFUN_IN="http://schemas.microsoft.com/[OracleDb://OracleDB_SADBR_FPW/SADBR_FPW/Procedures/PKG_ATRIBUFUN_INSERT]” elementFormDefault=”qualified” targetNamespace=”http://schemas.microsoft.com/[OracleDb://OracleDB_SADBR_FPW/SADBR_FPW/Procedures/PKG_ATRIBUFUN_INSERT]” xmlns:xsd=”http://www.w3.org/2001/XMLSchema”]
    [xsd:element name="SP_ATRIBUFUN_INSERT"]
    [xsd:complexType]

    Comment by Daniel Santana — December 9, 2008 @ 9:09 am

  13. Hi Daniel,

    Sorry, I haven’t done this with the oracle adapter. With the SQL adapter the adapter understands the multiple lines in the schema. But like you said – the root element can’t repeat so doesn’t look like it’ll work like with the SQL adapter.

    Comment by Thiago Almeida — December 9, 2008 @ 10:58 am

  14. [...] with BizTalk solutions: merging the contents of a flat file with a SQL Server database table. I wrote a post a while ago on how call the same stored procedure multiple times without a loop shape with the ‘old’ [...]

    Pingback by Using the BizTalk WCF-SQL Adapter to load a flat file into a SQL Server 2008 table « Connected Thoughts – Thiago Almeida — June 29, 2009 @ 4:20 pm

  15. this is excellent. may i have detail description of this problem? i will be very helpfull for me.

    Comment by nazmul — July 16, 2009 @ 10:59 pm

  16. I have a similar scenario :

    2 Schemas — SCHEMA-A and SCHEMA-B —> generated by SQL Adapter
    I have a Orchestration variable “ID”
    SCHEMA-A(Response)+ Variable needs to be Mapped to SCHEMA-B(Request)

    ROOT(SCHEMA-A-Response)(Multiple) >>>>>>>>>> ROOT (SCHEMA-B-REQUEST)(Multiple Insert)
    LNAME LNAME
    FNAME FAME
    ID (Variable inside Orchestration)
    How do i achieve this suggestions please.

    Thanks in advance..

    Comment by Reddy — July 19, 2009 @ 8:20 am

  17. This is an Excellent post

    Comment by RaviKumar Bhuvanagir — November 3, 2009 @ 7:59 pm


RSS feed for comments on this post. TrackBack URI

Leave a comment

Blog at WordPress.com.