Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / C#

Leveraging XLINQ Concepts in BizTalk 2004/2006 +

2.83/5 (3 votes)
29 Jul 2006CPOL2 min read 1   166  
Write a short code to solve your complex problem

Introduction

In this article, I am presenting an idea of leveraging XLINQ concepts in BizTalk 2004/2006 and future versions. XLINQ is part of LINQ and it's an enhancement to C# language. Please note the LINQ enhancements are in CTP phase while writing this article, so we cannot consider this as a proof of concept.

What is XLINQ?

LINQ (Language Integrated Query) is a code name for a set of language extensions to the .NET Framework. This is a clever way to Access the Data by building expressions like SQL. DLINQ is a set of components, which helps to translate the data between SQL and LINQ.

XLINQ is a straightforward and lightweight XML API, designed to simplify the ease of XML use from Memory and performance perspective.

Scenario

In 2003 year, I was integrating Siebel CME with other applications in our client network using BizTalk 2004. Siebel exposes UAN (Universal Application Network) layer for sharing common schema to the external applications. Siebel CME UAN 2.0 Package provides 12 Business process to integrate with other system, one among that is ProcessBilling process used for updating an order with corresponding information regarding each individual line item that was ordered. The source message looks similar as follows:

XML
<Orders>
    <LineItem Code="101"> 
        <User ID="UI023">
            <Product> <OpCode>ADD</OpCode>    
            <Name>Product A</Name>     <Qty> 1</Qty> </Product>   
        </User>
        <User ID="UI023">
            <Product> <OpCode>UPDATE</OpCode>   
            <Name>Product B</Name> </Product>
        </User>
        <User ID="UI024">
            <Product> <OpCode>ADD</OpCode>
            <Name>Product D</Name>  </Product>   
        </User>
        <User ID="UI024">
            <Product> <OpCode>UPDATE</OpCode>   
            <Name>Product E</Name>   </Product>
        </User>
    </LineItem >
    <LineItem Code="102"> 
        <User ID="UI023">
            <Product> <OpCode>DELETE</OpCode>    
            <Name>Product C</Name>   </Product>   
        </User>
        <User ID="UI024">
            <Product> <OpCode>UPDATE</OpCode>    
            <Name>Product D</Name>    </Product>   
        </User>
        <User ID="UI024">
            <Product> <OpCode>ADD</OpCode>   
            <Name>Product F</Name>        </Product>
        </User>
    </LineItem >
</Orders>

Destination system Portal net exposes three web service methods like "Add", "Modify" and "cancel" per user. We had to sort and group the big XML, based on Order ID, User ID and OpCode and call Infranet to process order with the sorted results. We tried writing Custom XSLT and faced difficulties in aggregating data that had a big performance issue. Then we had chosen .NET C# helper class and wrote code as follows:

C#
private static XmlDocument GetListSortedByUser(XmlDocument document, 
    out int RecCount)
{
            //Main arraylist to store the ordelines as it is from source
            ArrayList arrOrderLineItemsList = new ArrayList();
            // Get the order lines node list
            XmlNodeList xmlunl =  document.SelectNodes(xpathOrderLines,nsmgr);
            
            ArrayList objUserOperationCodeList = new ArrayList();
            
            // iterate for each order line and navigate through each order
            // line and add the operation code, orderid, and user id to the 
            // arraylist Towards the end of this for each loop add it to  
            // the main array
            foreach(XmlNode xmlNodeRdr in xmlunl)
            { ……………………………..
                if (xmlNodeRdr.SelectSingleNode(xpathOrderId,nsmgr) != null)
                { ………………..
                }

                // Add Operation Code to the array arrUserOperationCodeList 
                if (xmlNodeRdr.SelectSingleNode(xpathOperationCode,
                    nsmgr) != null)
                {
                    ….
                }
                // Get the party node list
                XmlNodeList xmlparty =  xmlNodeRdr.SelectNodes(xpathParty,
                    nsmgr);
                foreach(XmlNode xmlNodeParty in xmlparty)
                {
                if (xmlNodeParty.SelectSingleNode(xpathPartyRole,
                    nsmgr) != null)
                    {
                    ……………….    
                    }
                }
            // Separate Arraylist to hold the orderline values stored above based on the 
            // operation code
            // Delete operation code arraylist
            ArrayList arrDeleteList = new ArrayList();
            // Add operation code arraylist
            ArrayList arrAddList = new ArrayList();
            // Update operation code arraylist
            ArrayList arrUpdateList = new ArrayList();

            // For loop to add each order line to its arraylist based on its 
            // operation code value
            for(int i = 0; i lessthan objUserOperationCodeList.Count; i++)
            {
                object eachLineDetails;
                eachLineDetails = objUserOperationCodeList[i];
                ArrayList tempArrayList = new ArrayList();
                tempArrayList = (ArrayList)eachLineDetails;

                if(tempArrayList[1].ToString().Trim() == "Delete")
                    arrDeleteList.Add(objUserOperationCodeList[i]);
                if(tempArrayList[1].ToString().Trim() == "Add")
                    arrAddList.Add(objUserOperationCodeList[i]);
                if(tempArrayList[1].ToString().Trim() == "Update")
                    arrUpdateList.Add(objUserOperationCodeList[i]);
            }
            arrDeleteList = PerformSort(arrDeleteList);
            // Call the method to perform sort on add arraylist
            arrAddList = PerformSort(arrAddList);
            // Call the method to perform sort on update arraylist
            arrUpdateList = PerformSort(arrUpdateList);

            objUserOperationCodeList.Clear();

            // Add the sorted Delete arrayList to this new arraylist
            for (int i=0; i lessthan arrDeleteList.Count;i++)
            {
                objUserOperationCodeList.Add(arrDeleteList[i]);
            }
            // Add the sorted Add arrayList to this new arraylist
            for (int i=0; i lessthan arrAddList.Count;i++)
            {
                objUserOperationCodeList.Add(arrAddList[i]);
            }
            // Add the sorted Update arrayList to this new arraylist
            for (int i=0; i lessthan arrUpdateList.Count;i++)
            {
                objUserOperationCodeList.Add(arrUpdateList[i]);
            }
                    
            // the for loop to iterate through each order line and 
            // construct the xml back
            // from the grouped and sorted values in arraylist
            int iter=0;
            // iterate through each order line node
            foreach(XmlNode xmlNodeRdr in xmlunl)
            {
                document = new XmlDocument();
            }
return document;
}

Nearly 300 lines of C# helper code was written just for Sorting and Grouping.

How Do We Achieve the Same in XLINQ?

C#
XElement OrdersGrp = 
    new XElement("Orders",
    from user in orders.Descendants("User")
    from userid in user.Attributes("ID")
    group user by (string)userid into userGroup
    let userid = userGroup.Key
    select 
        new XElement("User",
        new XAttribute("ID",
        userid), 
        from user in userGroup 
        from opCode in user.Descendants("OpCode")
        group user by (string)opCode into opCodeGroup
        let opCode = opCodeGroup.Key
        select 
            new XElement("Product", 
            new XElement("OpCode",
            opCode), 
            opCodeGroup.Descendants("Name")
         )));

Only one line huh???? ( well, I consider lines by ; semicolon) and here is your expected output:

XML
<Orders>
  <User ID="UI023">
    <Product>
      <OpCode>ADD</OpCode>
      <Name>Product A</Name>
     </Product>
    <Product>
      <OpCode>UPDATE</OpCode>
      <Name>Product B</Name>
      </Product>
    <Product>
      <OpCode>DELETE</OpCode>
      <Name>Product C</Name>
      </Product>
  </User>
  <User ID="UI024">
    <Product>
      <OpCode>ADD</OpCode>
      <Name>Product D</Name>
      <Name>Product F</Name>
      </Product>
    <Product>
      <OpCode>UPDATE</OpCode>
      <Name>Product E</Name>
      <Name>Product D</Name>
     </Product>
  </User>
</Orders>

Conclusion

XLINQ opens a new way to simplify your data access from XML, in turn allowing you to develop very productive Biztalk interfaces.

Biztalk messages can be sorted and grouped. If anyone is interested, they can write a Generic functoid for sorting messages in the map.

Get your source code here.

Start dreaming about your next step in XLINQ and let me know about your updates... Cheers.

All the code in this article has been compiled with Microsoft LINQ project May 2006 CTP.

History

  • 29th July, 2006: Initial post

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)