Saturday, July 25, 2009

Range() and LinqToXml

A couple of days back, I was working on some dashboard components for our portal that use fusion charts. I was generating empty XML templates when I ran into a bit of a challenge: I had to generate 30 "category" nodes that were, basically, dates, and also empty data values for each of those dates. The trick was that the dates had to be based on the day the Chart was accessed.

Well, to be fair, it wasn't really "a challenge", just one of those pain in the ass-spaghetti-stinky piece of code that sometimes we have to write to go on with our lives.

I hated the idea to have some ugly loop (since I discovered linq, all loops are ugly!) that iterated 30 times and grabbed the current date the chart was accessed and then subtracted the index of the loop, and finally made sure that the result was sorted ascending.

So Range function and LinqToXml came to the rescue! Actually, I didn't know that Range() was available in .Net. A co-worker pointed out to me that I did exist and that it was under the "Enumerable" Class. (Thanks Connor!)

So, the potentially "ugly" loop ended up being a beautiful one-liner linq query:

Dim category = (From index In Enumerable.Range(0, 30) Select _
<category label=<%= DateTime.Now.AddDays(-index).ToString("M/dd") %>/>).Reverse

Man, Linq rocks! I can't stop saying it. Well now that I had the hard part done, I had left to generate some empty data sets and then put it all together:

Dim emptySets = From index In Enumerable.Range(0, 30) Select <set value="0"/>

'Build the Xml template
Dim chartData = <?xml version="1.0" encoding="utf-8"?>
<chart>
<categories>
<%= category %>
</categories>
<dataset SeriesName="Name1">
<%= emptySets %>
</dataset>
</chart>

'return the build template to the calling function
Return chartData.ToString

So the ouput of my query would look like this:

<chart>
<categories>
<category label="6/26"/>
<category label="6/27"/>
<category label="6/28"/>
<category label="6/29"/>
<category label="6/30"/>
<category label="7/01"/>
<category label="7/02"/>
<category label="7/03"/>
<category label="7/04"/>
<category label="7/05"/>
<category label="7/06"/>
<category label="7/07"/>
<category label="7/08"/>
<category label="7/09"/>
<category label="7/10"/>
<category label="7/11"/>
<category label="7/12"/>
<category label="7/13"/>
<category label="7/14"/>
<category label="7/15"/>
<category label="7/16"/>
<category label="7/17"/>
<category label="7/18"/>
<category label="7/19"/>
<category label="7/20"/>
<category label="7/21"/>
<category label="7/22"/>
<category label="7/23"/>
<category label="7/24"/>
<category label="7/25"/>
</categories>
<dataset SeriesName="Name1">
<set value="0"/>
<set value="0"/>
<set value="0"/>
<set value="0"/>
<set value="0"/>
<set value="0"/>
<set value="0"/>
<set value="0"/>
<set value="0"/>
<set value="0"/>
<set value="0"/>
<set value="0"/>
<set value="0"/>
<set value="0"/>
<set value="0"/>
<set value="0"/>
<set value="0"/>
<set value="0"/>
<set value="0"/>
<set value="0"/>
<set value="0"/>
<set value="0"/>
<set value="0"/>
<set value="0"/>
<set value="0"/>
<set value="0"/>
<set value="0"/>
<set value="0"/>
<set value="0"/>
<set value="0"/>
</dataset>
</chart>

So, there it is. no messy loops, no smelly code, just ....Linq.
Hope this helps

No comments: