Incorporate LINQ in your BizTalk projects

LINQ is something that has had my full attention ever since it was released. And I?ve been wanting to do something on this blog with LINQ, but never really found the inspiration to do something ?special? with it. Up until now.

So it occurred to me that there is not (to my knowledge) anything available that allows you to incorporate your LINQ way-of-work with BizTalk. And why not? There are purposes enough to use LINQ in a BizTalk environment, and it doesn?t even have to be rocket science to get there. On the contrary, using LINQ for BizTalk is about as easy as it can get really. And the means of use for this are limitless. Let?s go through some of the possibilities.

NOTE: Throughout this article, you will see a few different ways of how we could incorporate LINQ in our day-to-day BizTalk development. Iin good practice, we will NOT try to re-invent hot water. Instead, we will gratefully use existing functionality through LINQ to objects, and LINQ to XML.

A first example of LINQ usage in BizTalk is re-using BizTalk objects to provide a central BizTalk Administration Console. The advantages of this are obvious: we don?t have a need for a local Windows application to view our ports, locations, orchestrations and schemas. Instead, we can incorporate all BizTalk hubs from an infrastructure into one administration site where we can query administration information, start and stop our ports, and so on. One way we can do this, is through LINQ. The following will show you how.

When you install BizTalk Server, a number of assemblies are installed to the install location. By default, this is C:\Program Files\Microsoft BizTalk Server 2006. In this directory, there is one particular assembly that draws attention, namely Microsoft.BizTalk.ExplorerOM.dll. When we would take a look at this assembly through the Reflector tool (http://www.red-gate.com/products/reflector/), we would typically see a definition like this:

clip_image002

The BtsCatalogExplorer object is the central part of this project, that is because of the following properties it holds:

clip_image004

And these are just a glimpse of the properties. In general, you can say that the BtsCatalogExplorer object ?represents? one Administration Console, or one BizTalk Management instance.

So what is the problem? We could just take those collections and fire up some LINQ queries on that, right?

Well, unfortunately no. The collection objects in the BizTalk assembly are all implementing the IEnumerable and ICollection interface. No surprises, but unfortunately, also no LINQ available with extension methods. Yet this really is the key to where we want to go to, and the solution is as easy as a HelloWorld solution. We simply have to create our own object that contains a BtsCx atalogExplorer object, and cast the collection properties to generic list objects that implement IEnumerable<T>, which we need when we want to use LINQ methods in LINQ to object. When we take the SendPort collection as an example, basically what we need to do is this:

clip_image006

What we do here, is take the BtsCatalogExplorer object, and instantiate it through btsex. In order, we then cast the SendPortCollection to an IEnumerable<SendPort> through the OfType<T> method, which we then convert to a List<SendPort> through the ToList<T> method. The result is a generic List object of SendPort object, that implements IEnumerable<T>. Now that we have this LINQable object, we can do something like the following in any client environment:

clip_image008

It is a very basic, very simple example, but it shows how easy it is to introduce LINQ into the administration side of BizTalk.

Now there also is a processing side to BizTalk. Wouldn?t it be great to incorporate LINQ to that side as well? Now you can. The following example will demonstrate a simple tool to promote properties through LINQ, and I call it the LINQPromotor Pipeline Component. For this example, I will show the results first, and then the method used.

So let?s start off by summarizing the requirements. For this demo it is sufficient that we use one component per property we want to use. So the component needs to take in a property name to promote, a namespace, and a LINQ query to retrieve the value to promote. So typically, we want a configuration like this:

clip_image010
clip_image012
When we use this pipeline on an incoming message, we see the following when we query the message context:

clip_image014

Note that there are some things marked with red to draw attention. First of all, in the pipeline configuration properties, you see the PropertyName and PropertyNamespace values configurable. These are values are shown in the context where you see Name = PromotedByLinq and Namespace = http://schemas.linq.com/promotions/.

But the key here is the LINQ statement property. Instead of an XPath query that we would fill in to retrieve the value to promote, we actually write a LINQ statement to do that query. This makes the query easier to read and to configure.

One way to do this is through runtime compilation. Take the linq query in as a string, add it to a method that takes in an XElement object, compile it at runtime, execute and promote the returned string. That summarizes the way of work in this example. Now we will take a closer look.

First of all, the linq statement gets inserted in a stringbuilder that builds up a piece of code that contains one method with one parameter of type XElement, and that returns a string as the value:

public string GetVal(XElement element){}.

We then compile that piece of code using the CSharpCodeProvice object, that is located in the Microsoft.CSharp namespace.

clip_image016

Note that in order to use LINQ, you need to specify the CompilerVersion to v3.5. MSDN documentation will specify a version ?3.5?, but ?v3.5? is what you want to use.

The code is compiled in memory, so we can just return an assembly ob ject, create an instance of the class we generated, and invoke the method:

clip_image018

The string that is returned contains the value that we can simply promote in our IBaseMessage object through outMessage.Context.Promote(PropertyName, PropertyNamespace, value);

And the results speak for themselves.

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Posted by: Jan
Posted on: 7/2/2009 at 3:28 AM
Categories: C# | BizTalk
Actions: E-mail | Kick it! | DZone it! | del.icio.us
Post Information: Permalink | Comments (19) | Post RSSRSS comment feed

Comments