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:
<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:
private static XmlDocument GetListSortedByUser(XmlDocument document,
out int RecCount)
{
ArrayList arrOrderLineItemsList = new ArrayList();
XmlNodeList xmlunl = document.SelectNodes(xpathOrderLines,nsmgr);
ArrayList objUserOperationCodeList = new ArrayList();
foreach(XmlNode xmlNodeRdr in xmlunl)
{ ……………………………..
if (xmlNodeRdr.SelectSingleNode(xpathOrderId,nsmgr) != null)
{ ………………..
}
if (xmlNodeRdr.SelectSingleNode(xpathOperationCode,
nsmgr) != null)
{
….
}
XmlNodeList xmlparty = xmlNodeRdr.SelectNodes(xpathParty,
nsmgr);
foreach(XmlNode xmlNodeParty in xmlparty)
{
if (xmlNodeParty.SelectSingleNode(xpathPartyRole,
nsmgr) != null)
{
……………….
}
}
ArrayList arrDeleteList = new ArrayList();
ArrayList arrAddList = new ArrayList();
ArrayList arrUpdateList = new ArrayList();
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);
arrAddList = PerformSort(arrAddList);
arrUpdateList = PerformSort(arrUpdateList);
objUserOperationCodeList.Clear();
for (int i=0; i lessthan arrDeleteList.Count;i++)
{
objUserOperationCodeList.Add(arrDeleteList[i]);
}
for (int i=0; i lessthan arrAddList.Count;i++)
{
objUserOperationCodeList.Add(arrAddList[i]);
}
for (int i=0; i lessthan arrUpdateList.Count;i++)
{
objUserOperationCodeList.Add(arrUpdateList[i]);
}
int iter=0;
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?
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:
<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