Passing a List to a SQL 2008 stored procedure

Background

Ever since I started out working with stuff like Data Access, SQL server, stored procedures and all that sort of gizmo's, I felt a need in certain situations for a stored procedure that is able to take in some kind of array, list, table of items and insert them in a table. This pops out the most in many-to-many relationships between tables. You'd take a .NET object, fill it up with several List<T> properties to hold that sort of info, and then what? Loop over them and open up a set of DB connections for each item? Parse the list into a comma separated string? Or parse it into an xml to process on the server? Sure, they all work, but it's a lot of work every time you need to do it. And between you and me, I'm not too fond of xml processing in SQL Server myself?

Eureka!

So after all those years (well I'm still young, so maybe not all THOSE years) I finally found ONE answer to my problem. Let me repeat the ONE keyword here, because in all honesty, I'm not even sure if this is actually a decent way to get things done. The only thing I guarantee is that it works for me, and kind of makes sense in how it works too (talk about luck!)

How it's done

Part 1: SQL Server

Starting out with the SQL Server part. Keep in mind a tiny scenario where we have a List<Person> object, that we want to insert into a table.

The first thing to do is create a User-Defined Table Type in SQL Server.

image

So first thing to notice is this is actually the same syntax as to create a regular table, except for the keyword TYPE ? AS TABLE. The rest of it is basic column definition. For simplicity reasons, we only keep track of an Id, a surname and a first name.

Next thing to do is to create the table itself. I'll create them with the same column names for the ease of it, but this of course, is not a restriction.

image

And to top it off, I'll add a stored procedure to the party that takes care of the insert logic.

image

So the parameter for this stored procedure is of the User-Defined Table Type Person. This needs to be marked as READONLY, otherwise the procedure won't get created.

Part 2: .NET

Now that the SQL part is out of the way, it's time to start the work in .NET. Let's take a step back and go over what needs to be there. We will definately need:

  • A Person object to hold the properties
  • A List<Person> to hold the people that need to be added to the table
  • Some kind of hocus-pocus to transform a List<T> to a DataTable(System.Data)

Going in a chronological order, we start out with the object itself, which as suspected, is nothing magic.

image

Next on the list is adding some folks to a List<Person>:

image

 

Now, the biggest piece of work in all this would be to parse the List into a DataTable object. Considering the fact that the amount of possible objects is, well, infinite, you shouldn't be translating every single object to a DataTable right? Right. So my solution is to have a DataTable<T> object that holds a List<T>, and translates every property of T into a DataTable object. Nice and easy!

image

And if you remember the List<Person> object that was created a minute ago, called persons, all we need to do now is call the stored procedure to insert those persons in the table:

image

Part 3: the outcome

So when this small project started out, there was this situation at hand:

image

Now when I run this app, we get this:

image

 

Conclusion

There is a little bit of prep work to do with this solution, in configuring the SQL objects etc. But then again, all database designs require prep work, so that's something I'm willing to let slide. But to this day, it's the first easy to implement solution I have to a problem I've been dealing with for over four years now.

Currently rated 1.0 by 1 people

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

Posted by: Jan
Posted on: 10/23/2009 at 1:47 PM
Categories: .NET General | C#
Actions: E-mail | Kick it! | DZone it! | del.icio.us
Post Information: Permalink | Comments (5) | Post RSSRSS comment feed

The big battle: Recursion vs Iteration

 

During my (short) times as a developer, I've come across a few situations where recursive method writing was in order. However, when I look back on a recent conversation I had about recursion, I started wondering why I would ever want to write something recursive. Because it's "clean" code' Because it's cool to say: "hayooo! I wrote something recursive!"? Who knows? One constant factor that is always certain, is that you want to write methods that execute in the most performant way possible. And that is where recursion just won't cut it'

Keeping the old Fibonacci post of a few weeks back in mind, I started investigating versions. The result is a small app that has two methods, one that calulates the x'th number using loops, and one that does the same using recursion.

 

image

image

The result either way:

image

Already from the beginning, the time difference in calculation between the two methods is noticable. Quite obvious, actually.

So now it's time to do some deeper investigation. For this case, I used a trial version of dotTrace to view the application. When the monitoring of the non-recursive method was done, the big part of the trace was as follows:

image

10ms to run the actual calculation of the "Looped" method. Nice! No biggie, all is great. Looks performant. Happy feelings. So what about the recursive method? Two simple lines of code vs a little more work in code? Let's see:

image

Are you kidding me? No of course not. This is kind of expected too, since you always keep on calling methods? And every method call consumes memory, resources... So yeah, big shocker that recursion is not as performant as iteration.

Is that a bad thing? No! Recursion is a great methodology to see things a little different than we normally do. You'll think of the algorithm more than the implementation itself, which to me is a good thing from time to time.

However, if one intends to use recursion in an intensive, deep-leveled method, I'd say think about writing "uglier" code with iterators. It might not save a lot of dev time, but it will probably save you heaps in processing and execution time.

And at the end of the day, execution time is what it's all about, right?

Currently rated 4.5 by 2 people

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

Posted by: Jan
Posted on: 7/24/2009 at 6:24 AM
Categories: .NET General | C#
Actions: E-mail | Kick it! | DZone it! | del.icio.us
Post Information: Permalink | Comments (33) | Post RSSRSS comment feed

A wild adventure with Haskell, Fibonacci and .NET 4.0

Last Monday I was starting with a personal little challenge, recommended by Bart De Smet (http://community.bartdesmet.net/blogs/bart/Default.aspx). It was about Haskell, a compact functional programming language Definition from Haskell itself: "Haskell is an advanced purely functional programming language. An open source product of more than twenty years of cutting edge research, it allows rapid development of robust, concise, correct software. With strong support for integration with other languages, built-in concurrency and parallelism, debuggers, profilers, rich libraries and an active community, Haskell makes it easier to produce flexible, maintainable high-quality software."

So thinking about the fact that a "Hello world" thing wouldn't cut it, I thought I might as well make a little Fibonacci calculator toy that takes in the number of the element in the row (eg the 5th element) and return me that value. That part got me to a recursive function like this:

fib :: Integer -> Integer
fib n
    | n == 0  = 0
    | n == 1  = 1
    | n  > 1  = fib (n-1) + fib (n-2)

I then started testing it out. fib 1 = 1; fib 5 = 5; fib 6 = 8; fib 7 = 13 and so on. However, all of a sudden I tried to do a fib 356. BIG MISTAKE!!!! The recursive part of the function didn't really like the whole 356 loops thing :) but this is actually where the fun part started.

I put a playful post up on my facebook saying that counting the 356th element of Fibonacci is hard even for a computer. Nothing more nothing less. Only a few minutes after that, I get the answer from Bart saying that it's: 69362907070206748494476200566565775354902428015845969798000696945226974645

Now THAT is a big number! Now being the alltime challenger that Bart is, he asks me how he managed to get that kind of precise number. Clearly int32 won't cut it in here, and double, long and all that is not sufficient either.

So I open up my Visual Studio environment and start puzzling but don't find the answer right away. At that point Bart was offline again so that bought me some time :) My "quick" solution was to split up the value of the number into smaller integer parts, and then pasting them back together in a string when it needed to be shown. I gave that answer on my facebook and he just simply says: System.Numerics.BigInteger in .NET 4.0

"DAMN YOU!" was my shocked reaction. All that time he was living it up with .NET 4.0 that has a BigInteger class while I was mindcrushing myself to find a solution.

So there are some conclusions to keep in mind from this adventure and post:

1. .NET 4.0 might have some fun new toys to make life easier :)
2. It's mighty fun to be mentally challenged!
3. I hope I impressed the showoff :p (Bart, if you?re reading this? :p)

Currently rated 4.0 by 1 people

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

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

Processing custom WCF header values at server-side

Well since my previous post was about passing information from client to server in a WCF header, this post is about processing
the incoming header to retrieve the original username.
If you read my previous post, I used a class RequestAuth and ProcessAuth. This post will explain the ProcessAuth class.
This time I need to FETCH something from the message, so instead of implementing IClientMessageInspector, I need to implement the IDispatchMessageInspector interface,
together with the IEndpointBehavior interface again, and I need to inherit from BehaviorExtensionElement again, so I can add this
functionality to my endpoint behavior.
In the previous post, I explained that it can be convenient to override BehaviorType and CreateBehavior, so I'll do this again:
        public override Type BehaviorType
        {
            get { return typeof(ProcessAuth); }
        }
        protected override object CreateBehavior()
        {
            return new ProcessAuth();
        }
Also, to store the current user to send to the server, I'll hold a private field userName:
[System.Diagnostics.DebuggerBrowsable(System.Diagnostics.DebuggerBrowsableState.Never)]
private string userName;
Now, for the IDispatchMessageInspector implementation, it's fairly simple when you think about it. At client-side, I implemented the
BeforeSendRequest of the IClientMessageInspector interface. Now I am at server-side level, so I need to implement AfterReceiveRequest of
the IDispatchMessageInspector interface.
        public object AfterReceiveRequest(ref System.ServiceModel.Channels.Message request, System.ServiceModel.IClientChannel channel, System.ServiceModel.InstanceContext instanceContext)
        {
            sUser = request.Headers.GetHeader<string>("SomeName", "http://SomeNameSpace", "Anyone");
            return CheckSecurity();
        }
NOTE: I'm using the same name and namespace for the header as I did at client-side level. This is of course very logically that those two
need to be the same :) otherwise you would never get the right values.
At the end of the method I return CheckSecurity(). This is a boolean method which you can implement at your own needs, it just returns true
or false depending of the access-allowed level of the requesting user.
And that's it for the MessageInspector part! Of course, we also need to add this inspector to every incoming request. This is where theIEndpointBehavior interface comes in again. However, instead of implementing the ApplyClientBehavior method (client-side), we need
to implement the ApplyDispatchBehavior this time, for server-side.
        public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)
        {
            endpointDispatcher.DispatchRuntime.MessageInspectors.Add(this);
        }
THAT'S IT FOR THE SERVER SIDE!!!
Adding this to your server endpoints can be done in the same way I did it in the client configurations.
TO SUMMARIZE: Well, we actually did a lot of work in here with very little code writing. But in my opinion, this shows a nice feature of
customizing WCF.
With this example, you can use your own WCF headers to send some information to the server, and process it there. And not only that, but
you can do this completely automatically by using custom endpoint behaviors.
So that's it concerning my first blogpost :) hope you enjoyed, and feel free to give some feedback!

Currently rated 5.0 by 2 people

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

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

Automate passing valuable information in WCF headers

This post is about passing through some information at the client to the server, and how to automate this using the WCF configuration.
Case study:
I was with a client, developing WCF services which are hosted on IIS. Since they already have a wide range of security settings stored in databases, it would be a shame to let go of those configurations and force a whole new security model on them instead of trying to integrate their configs into the services.
We have several end users surfing to an intranet site (which is our WCF client), while the site communicates with several servers running WCF services on IIS. The site runs under a simple network service so the Windows Authentication is guaranteed server-side.
But to ensure security for several users (not everyone is allowed to view the same information) we want to pass the current username to the WCF service, and perform a security check with the client configurations, before returning any results.
How do we do this? Well there are probably tons of solutions available, but the way that worked the easiest for me (and my client) is working with custom behaviors on the endpoints, where the username will be passed in a WCF header.
So we need two classes: one to add the header client-side, and one to process the username server-side. In my example, I call them RequestAuth and ProcessAuth. Let's start out with RequestAuth.
Since I want to add something to the message at the endpoint level, I'll need to implement the IClientMessageInspector interface, which is found in the System.ServiceModel.Dispatcher namespace, and the IEndpointBehavior interface, in the System.ServiceModel.Description namespace. BUT, since we are going to add this to a behavior, we need to inherit from the BehaviorExtensionElement class, in the System.ServiceModel.Configuration namespace.
Now before we start implementing, bare in mind that it might come in handy to override the BehaviorType property of BehaviorExtensionElement, as well as the CreateBehavior() method. This is done easily by doing:
    public override Type BehaviorType
    {
            get { return typeof(RequestAuth); }
    }
    protected override object CreateBehavior()
    {
            return new RequestAuth();
    }
Also, to store the current user to send to the server, I'll hold a property UserName:
[System.Diagnostics.DebuggerBrowsable(System.Diagnostics.DebuggerBrowsableState.Never)]
private string userName;
    public string UserName
    {
            get { return userName; }
            set { userName = value; }
    }
Note: by using the System.Diagnostics.DebuggerBrowsable attribute and setting it to never, no client will ever get to see the private fields in your code. Not only is this safer, but it also gives a better debugger view when debugging.
Now, while it is not necessary anymore in .NET 3.5 to link a property to a private field, this example was written in .NET 2.0, so if you are redoing this in 3.5 you won't need the username field.
On to the implementations then! At first, I have to implement the IClientMessageInspector members.
Keeping in mind that I am SENDING something to the server, I only need to implement the BeforeSendRequest method.
So we need to make a MessageHeader object of string to send the username. After that, I try to retrieve the current logged on user.
In here I needed to make a difference between web applications and desktop applications. But if you are certain that you will ALWAYS
run in one environment (web or desktop) you can drop the check and keep the right username
Now, before I did the actual implementation, I keep a name and a namespace for my header in two private fields, so I can easily find
them back server side.
    [System.Diagnostics.DebuggerBrowsable(System.Diagnostics.DebuggerBrowsableState.Never)]
        private string hName = "SomeName"; //use your own name for the header in here
        [System.Diagnostics.DebuggerBrowsable(System.Diagnostics.DebuggerBrowsableState.Never)]
        private string hNameSpace = "http://SomeNameSpace"; //use own namespace here
        public object BeforeSendRequest(ref System.ServiceModel.Channels.Message request, System.ServiceModel.IClientChannel channel)
        {
            MessageHeader<string> header = new MessageHeader<string>();
            header.Actor = "Anyone";
            //Keep the difference between web environments and desktop environments
            if (System.Web.Hosting.HostingEnvironment.IsHosted)
            {
                if (OperationContext.Current != null)
                    UserName = OperationContext.Current.ServiceSecurityContext.WindowsIdentity.Name;
                else
                {
                    if(System.Web.HttpContext.Current != null)
                        UserName = System.Web.HttpContext.Current.User.Identity.Name;
                }
            }
            else
                UserName = System.Threading.Thread.CurrentPrincipal.Identity.Name;
            //Add the username to the header
            header.Content = UserName;
            //Creating an untyped header to add to the WCF context
            System.ServiceModel.Channels.MessageHeader unTypedHeader = header.GetUntypedHeader(hName, hNameSpace);
            //Add the header to the current request
            request.Headers.Add(unTypedHeader);
            return null;
        }
So the previous code snippet will add a string containing the username to the WCF request. But to do this for every request, we still
need to add the MessageInspector we just implemented to the behavior. So on to the implementation of the IEndpointBehavior interface!
Well there's nothing much to it in this part, but to use the current clientbehavior and add the inspector:
        public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime)
        {
            clientRuntime.MessageInspectors.Add(this);
        }
NOTE: I use <this> as parameter, because the class we are working in IS a message inspector, thanks to the IClientMessageInspector interface
we implemented.
THAT'S IT FOR THE CLIENT SIDE!!! If you build this in an assembly and sign it, you will be able to add this in your WCF config file.
HOW? Simple: Open your WCF config file with the WCF Config Editor tool (SvcConfig.exe). Under the "Advanced" node, within "Extensions", you have
a node "behavior element extensions". That's where you click New, give your extension a name, and browse to your newly created assembly, and select
the correct behavior element to add (if you have multiple in one assembly). In this case, you need to select the RequestAuth item.
Once this is done, you can navigate to your Endpoint Behaviors, and in your behavior, if you click Add, you will see the new extension in the
list of available extensions. From now on, every service that uses this endpoint behavior will add the new username header to every outgoing request
it makes.

Currently rated 5.0 by 1 people

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

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

Terminating BizTalk instances: WMI vs Operations

The Administration console that is delivered with the installation of BizTalk allows a user to query suspended service instances and resume or terminate them accordingly. However, when you want to go ?outside the box?, and I often do :) you might want to consider finding out possibilities of doing those actions yourself, for instance from a web based managing platform. (note: the following methods work for both BTS2006 and 2009)

When you install BizTalk, there is a WMI provider installed on your machine as well, located in the root/MicrosoftBizTalkServer namespace. That namespace actually provides just about every functionality you need for administration purposes. But in this case, I typically want to focus on the MSBTS_ServiceInstance class. (this is a snapshot taken from server explorer in VS2008)

image

If you right click the class and generate an instance, your current project will get an extra class called ROOT.MicrosoftBizTalkServer.MSBTS_ServiceInstance.cs. When you take a look at that class, you will see the three methods that I?m interested in at this moment: Suspend, Resume, and Terminate. Let?s focus on the Terminate example for this case.

If you want to terminate a service instance through WMI (and there are examples of that over the entire web, so let?s NOT get into that deeply), you can simply use the generated class and say something like:

image

When you provide the InstanceID of your service instance, together with the name and server of the BizTalk Management Database of the BizTalk environment you are working on, the generated class will construct the WMI query for you and execute behind the scenes. So what you need to keep in mind with this method is that you need to go through the entire WMI architecture before actually taking an action.

To me, it sounds easier if I could do the same action in a more direct approach to BizTalk. And lucky for both me as the people who read this (at least I hope people read this :)) we can do that!

When you go to the root install directory of BizTalk (typically that?s C:\Program Files\Microsoft BizTalk Server) you will notice an assembly called Microsoft.BizTalk.Operations.dll, which in this case you can compare to a holy grail :) Let?s take a quick peek at the assembly with Reflector:

image

Of course now every still-awake reader notices the same methods I previously stated. And using these methods are of the same ease as the WMI methods. It goes as follows:

image 

Parameters stay the same. Create an instance of the BizTalkOperations class using the servername and database name of the BizTalk Management Database, and terminate your instance using the InstanceID of the Service Instance object.

Not much difference at first sight, but the thing here really is that when using the BizTalk.Operations, you have a more direct database approach to your action, instead of going through the entire WMI system before actually doing something. Sounds like that could save some performance when you would terminate instances with 500 at a time.

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:30 AM
Categories: C# | BizTalk
Actions: E-mail | Kick it! | DZone it! | del.icio.us
Post Information: Permalink | Comments (45) | Post RSSRSS comment feed

Persist message context when re-injecting a message in BizTalk

There are many cases in BizTalk environments when one want to re-inject a message into their system. I?m mainly referring to testing environments where it doesn?t really matter if a message is repeated.

However, it can also be preferred to copy the context of the message into the newly injected message, because your system might want to do some processing of that context while re-injecting. When you do this from code, it?s a snap!

First of all, we need to load up our message body and context:

image

Note that you need to specify the sql server name and database name of the BizTalk Tracking Database (commonly named BizTalkDTADb, but you can configure any database name). The System.GUID attribute should be replaced with the message id of the message you want to re-inject.

Now that we have an IBaseMessage object, we can access the context and copy it to the context of a new out IBaseMessage object.

 

image

 

This way we can keep a difference between promoted context properties and standard context properties. And that?s the only thing to it, msg_out is ready to be re-injected
to the BizTalk system

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:29 AM
Categories: C# | BizTalk
Actions: E-mail | Kick it! | DZone it! | del.icio.us
Post Information: Permalink | Comments (30) | Post RSSRSS comment feed

Mathematical nostalgy

There is a time in every person?s life where one likes to recap about long lost projects. Little pieces of code that made you happy inside once it was completed. Well today, I had this moment.

The project I?m talking about is something I came up with after a school lesson on fractals. I won?t be getting much into that, as I am assuming everyone knows what that is. But once that session was done, I grabbed my laptop and went to work. The fractal that originated from that piece of free time is something that made me proud up until today.

Note: I completely made this fractal up from my imagination, if the same fractal already exists, and I?m sure it does, I don?t know about it but would like more info on it.

So anyhow, I was browsing through some old folders on my external disk and discovered that I had deleted that entire project to make room for other stuff. Disappointment went through my entire body and mind. But that didn?t take too long, as I decided to re-write it. Here?s  how I did it:

Basically, the top design of the fractal would be something like this

image

 

A tree-like structure that keeps getting smaller in a repetitive pattern. The tricky part is of course always defining your endpoint. The start point is never a problem, because that?s the endpoint of the previous branch. But the endpoints? they make it a little hard on my head :)

Now there are probably a lot more solutions available to this problem, but in my own case, I decided to go with good old trigonometry. Since the tree is built up using rectangular triangles, it?s pretty easy to come up with a formula that calculates the points needed.

image

x2 = x1 + (cos(alfa) * branchlength)
y2 = y1 - (sin(alfa) * branchlength)

Since I have a left part and a right part, I?m starting off with alfa = 135 and beta = 45. So I?m already done with the formula, on to the code translation!

First of all, it?s fairly logical that I declared a brush, a pen, and a graphics object, in my case called b, p, and g. Nothing fancy there :)

Next part is a littly cooler; in order to implement a configurable nesting level and draw everything with as little effort as possible, I chose to make a recursive method that takes a few parameters, namely a current X position, current Y position, current length, nesting level, an alfa angle and a beta angle, signatured as: private void DrawFrac(int xCur, int yCur, int lenCur, int nestCur, int alfa, int beta){}

So now the rest of the implementation is pretty easy (afterwards :) I busted my head on it for a while because the mathematical part had been a while since I used it)

if (_nestinglevel >= nestCur)
            {
                Point start = new Point(xCur, yCur);
                Point leftEnd = new Point((xCur + Convert.ToInt32(Math.Cos(alfa * (Math.PI / 180)) * lenCur)), (yCur - Convert.ToInt32(Math.Sin(alfa * (Math.PI / 180)) * lenCur)));
                g.DrawLine(p, start, leftEnd);

                Point rightEnd = new Point((xCur + Convert.ToInt32(Math.Cos(beta * (Math.PI / 180)) * lenCur)), (yCur - Convert.ToInt32(Math.Sin(beta * (Math.PI / 180)) * lenCur)));
                g.DrawLine(p, start, rightEnd);

                nestCur++;
                DrawFrac(leftEnd.X, leftEnd.Y, (lenCur / 4) * 3, nestCur, alfa+45, beta+45);
                DrawFrac(rightEnd.X, rightEnd.Y, (lenCur / 4) * 3, nestCur, alfa-45, beta-45);
            }

the result? a nice little fractal :)

 

frac

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:29 AM
Categories: C#
Actions: E-mail | Kick it! | DZone it! | del.icio.us
Post Information: Permalink | Comments (10) | Post RSSRSS comment feed

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