Tuesday, March 28, 2006

Yay me, and a question...

Firstly, yay me!

I don't care what you might think about the pros and cons of microsoft certifications. You may think they're pointless. You may think they're not worth the paper they're printed on.

Either way, I passed my first exam today. Woo and yay! 70-315 - I have a certificate that says I can "Develop and Implement Web Applications with Microsoft Visual C# .NET and Microsoft Visual Studio .NET". Woo!

The second thing was a question that someone actually asked me this morning that piqued my interest.

What this guy was trying to achieve was filtering on a Date field in a Dataview, but rather than filtering on a continuous date range, he was trying to filter on a series of date ranges.

Put simply, he wanted to pull out all the records that had a date somewhere in March (for instance). I don't know the exact context he was coming from, but it would be useful if, for example, you had sales data spanning a few years and wanted to see how things were looking on a month-by-month basis.


I discovered it doesn't seem to be as easy as all that to do. I started out by creating a Dataset in Visual C# Express, just by dragging the Employees table from the AdventureWorks database on my toolbar (Ah, the company name may change, but the samples stay the same!).

My goal was to pull out Employees as a DataTable in my dataset, create a DataView from it and filter the view to just contain everyone that has a birthday in March.

To start, I thought I'd create a new column populated with an expression, something along the lines of BirthDate.Month (or something similar). However, it looks like you can't do that. Although you can take DataColumns and do simple stuff to them, adding values, subtracting values etc, you can't do anything (it would seem) that's specific to a slightly more complex datatype, like a DateTime.

The next thing I though of was to try a do some quick filtering with a LIKE clause in the dataview's RowFilter property, so it looked something like 'view.RowFilter = "BirthDate LIKE '03/%'"' think I could pull out all the March birthdays that way. (n.b. I didn't have to worry about the formatting of the Date because of the culture insensitivity of the expression used to filter DateTime columns.)

Apparently not, though. Apparently you can't apply 'LIKE' and wildcards to DateTime fields. Which, I must admit, makes sense. I was pretty much clutching at straws when I went down that route.

So, to recap, I wanted to filter on a set of dates. These happened to be all the dates in March for a number of years, but that's by the by.

In then end, this was how I managed to do it. When I started out, I though it looked a bit hokey, and a bit of a fudge, but as I looked into it more, I'm actually quite impressed with it. It may not be that elegant a solution, but hey, it does tha job, and at the end of the day, if it works then that's cool.

TestAdventureWorks.dsTest data = new dsTest();
TestAdventureWorks.dsTestTableAdapters.EmployeeTableAdapter da =
new TestAdventureWorks.dsTestTableAdapters.EmployeeTableAdapter();
DataView view = data.Employee.DefaultView;

StringBuilder s = new StringBuilder();
int StartYear = 1945;
int Month = 4;
for (int i = StartYear; i < 2000; i++)
if (i != StartYear) s.Append(" OR ");
s.AppendFormat("BirthDate >= #{0}/01/{1}# AND BirthDate < #{2}/01/{1}#", Month, i, Month + 1);
view.RowFilter = s.ToString();
Console.WriteLine(string.Format("Rows: {0}", view.Count));
Console.WriteLine(string.Format("Total: {0}", data.Employee.Rows.Count));

I don't know what the performance is like on it, though. In this case, going through 55 years on a set of 290 rows took around 70ms to complete. Not too shabby, I thought. Considering the length of the RowFilter string that went into it!

However, my question is this (and if you've read this far, perhaps you know the answer!) Is there a better way of doing it?

I thought of 1, which is to pull out the month component of the date in the original select statement, so your SELECT would look something along the lines of 'SELECT *, Month(BirthDate) FROM Employees'. It acheives the same thing as my first plan, and would allow you to just set the RowFilter to be 'BirthDateMonth=3'. But that's cheating!

Anyway, just wanted to share.

Yay me!

Wednesday, February 22, 2006

This is what happens when developers aren't network guys...

In a previous post, I was confused over which user account TfsBuild.exe executes under. I kept on getting various file exceptions and whatnot.

Well now I know. It runs using the account you specified for all your Team Foundation Server Services to run under (In the installation guides, it's the one called domain/TFSSERVICE). I can't remember if I specified this account at install-time or not. But there you go.

Which brings me to the next thing that was causing trouble recently. I wanted to create a new build type that, as well as compiling my application, published it to our test server as well. Very quickly, it was just a matter of creating a new target in the .proj file called "AfterCompile" (overriding the one in the default .targets file), and adding an AspNetCompiler task to it for each website I wanted pushed up there.

Problem was, the TFS Service account couldn't see the folder I was deploying to. No problem. Browse to that folder in explorer, fire up the properties, grant TFS write access and bob's yer uncle. Right? Wrong.

After a couple of us pored over it for a while my boss' boss casually asked "Have you enabled write access to the share itself?" DOH! Although according to NTFS, the TFS account had write access to that directory, the initial fileshare (about 3 levels up) only had read access enabled. So I could browse to the directory I wanted to in explorer, but writing to it was being blocked by the share permissions.

I didn't know it worked like that. I figured NTFS alone governed the access level to that directory.

And that is what happens when developers aren't network guys.

Just wanted to share.

Thursday, February 16, 2006

Something I really could do with finding out...

... But I don't know how.

Here are a couple of things I know:

It's a shady proposition setting a timer running on a form, and doing a straight method call to update the form's display. It works sometimes, but because the timer runs (or at least can run ) on another thread to the rest of the form, it sometimes falls over.

There are a few nice elegant ways of sorting this all out and getting everything running properly in .NET 1.x, but .NET 2.0 brings with it the BackgroundWorker class.

Which is a nice thing, particularly if you want to do some long running processes and update your UI as they go.

This I know.

But what I don't know is: what does the timer do when it's not elapsing? Obviously it's ticking away, just... well... being a timer, but is that it?

What I'm getting at (albeit in a roundabout and thoroughly confused way) is this:

I have a countdown timer that updates the form every second. I can't just use a timer to do it and handle its Elapsed event, but what if I fired up a BackgroundWorker, and then just called System.Threading.Thread.Sleep(1000) in a loop, raising the ReportProgress at each cycle through the loop?

Is that a good idea? It seems to me to be the easiest, certainly the quickest way to achieve it, but is it really good practice? Thread.Sleep() always strikes me as being a bit of a hack, but it works.

I'm sure I'll work something out eventually. Who knows. Could be I'm doing it a good way. Doubt it, though.

Just wanted to share my bafflement. Of course, if anyone knows the answer, then let me know.

Monday, February 06, 2006

Scheduling builds using Team Build

Today I've been having big fun trying to get an automatic build schedule together for the project I'm working on at the moment.

Yes, that's right. Trying. Nearly there, and there are several things I've learnt along the way about Team Build. Here are the important ones (in no particular order):

1) There's no inbuilt scheduler.
No real biggie, but before you spend half the morning looking for it, know that it's not there to be found. You'll just have to schedule it to run via Windows' task scheduler.

2) The command line tool TfsBuild.exe rules
See 1. Actually, I must say, the command line tool is really useful. It lives at:
<TeamBuildInstallDir>\Common7\IDE\TFSBuild.exe and is surprisingly good.
It can be called using:

TfsBuild.exe start <TeamFoundationServer> <ProjectName> <BuildType>

As you might have guessed, it'll go to your TFS Server, find the build type you've specified, download the configuration from source control (the current checked in version) and build based on that. Which I think is really neat.

It's not without its quirks, though. I spent ages feeding it different renditions of our server name (http://server, http://server:8080, etc...) and it kept on saying it couldn't find the server I was pointing it at. I found this post from someone who was having exactly the same problem, though, and the solution at the bottom worked for me. Go into the registry and find HKEY_CURRENT_USER\Software\Microsoft\VisualStudio\8.0\TeamFoundation\Servers and add your server in there. Admittedly, I mimicked exactly what Joey Bradshaw did and put the friendly name of our server in as the key, and the full server name as the value. I don't know if the key is significant, but by this time I was getting hungry and wanted to go to lunch. Worked, though, which is the important thing.

3) Any kludges you've put together for getting your project to compile - better fix them properly
Yes, I know, this is pretty much the whole point of an automated build. But still. I came a cropper a couple of times with dll references.

We have a bunch of 3rd party and legacy dll's that we reference from our current project, which is fine. We keep them on a shared drive, the dll paths in the reference and the .refresh files in websites are pointing to that share, everything's happy. Until...

4) I'm buggered if I can work out what user account TfsBuild.exe runs under.
I kept on getting reports that the drive out shared dll's live on didn't exist. And fair enough, the standard shared drive mapping that all the developers use wasn't there. No biggie. Just log in under the account the Team Build service runs under, map the drive, and Bob's your uncle, yeah? No. Kept on getting the same errors reported that the drive didn't exist.

So I changed all the references in the source code to full network paths. Sorted, eh? No. Changed the permissions on the network share to allow the Team Build Service account read access, and it all worked fine. Go figure. It wouldn't pick up the drive I mapped under its account, but it's definitely the account that goes fishing about on the network to find those pesky dll's.

Oh well. It's done now.

So (at last!) I've got a successful build going on. Yeah?


5) Your project may well compile, but your Unit Tests might not...
Once I got my main project to build, I shifted my Test project from the old server to the new. Yeah yeah, I should have done all that when I first moved the rest of the project, but hey, this is me. It was Friday and I just wanted to get everything working and go home.

So I moved my Unit tests over, changed all the external references (as I had discovered already. Built fine. Go to run it? Nope. Unit Tests don't run at all. Compile fine, but won't run. You'll need to give the dll's in the shared folder elevated elevated privileges to get them to run (elevated from the normal Intranet code group, anyway).

6) There's nothing better on this earth than that little green tick!
No matter what people tell you. When you see that green tick, there's nothing better!

7) Once it all works, it Team Build really does rule!
The reports Team Build produces are so cool. They're so comprehensive, and the integration with the rest of Team Foundation Server is fantastic. Once your project builds, it'll go back and See what changes have been checked in since the last successful build. It'll find all the work items associated with those changesets, indicate on them all that those changes have made it into a build, and give you some friendly statistics and scary numbers to tell your boss.

It'll even create a new work item if it fails that links to the failed build report and tells you to fix it!

All in all. It's been a bit of work today, and it's not quite over yet. But we're now running automated nightly builds and loving every second of it!

Just wanted to share.

Friday, February 03, 2006

The Midas Touch

There are some people that just have the touch of gold for some things.

Carl Franklin is one of them.

I've been listening to DotNetRocks for a couple of years now, and it's always been fantastic. In fact, when I'm not talking to my boss, I crdeit my entire career to DNR. Obviously, I tell my boss it's all down to me being fantastic!

But now he's come out with DnrTV.

It does rule. I've seen much love in the blogosphere (although I hate that word!) to prove it.

The only thing I have trouble with is remembering everything. Not only do I have to seclude myself from the missus for an hour, but it is also like a total vulcan mind-meld taking it all in!

BUT. It does rule. It's right there on the top of my list of things to do when Mrs Mawoo is out.

PS - Nobody can ever beat Geoff's hair (nb Geoff is second from the right, the one up from the... well ... you'll spot him from his hair! It's the greatest, I have dreams where my hair is as cool as Geoff's!)

PPS - If anyone wants an MSN 8.0 Beta invite, just email me

PPPS - Did I say right? I Geoff's in fron the left! In fron the right is ActiveNick.

Friday, January 27, 2006

Have these always been here? Or am I being stupid?

In the code editor in VS 2005 (any edition I guess, but I've been using VS Team Edition for Software Developers):

  1. Right Click.
  2. Expand the 'Breakpoint' menu item.
  3. Click 'Insert Tracepoint'
  4. Enter a message

You'll now have whatever message you want printed out in the output window. It can print the calling method, stack trace and a whole raft of other stuff.

Although I'm quite inclined to use Trace.Write() in a web app (I figure if it's something you want to know when you're writing it initially, it'll be useful to know when it's actually in use), there are times when it's a bit of overkill putting a permanent trace in for some of the stuff you're debugging.

Neat eh? I've just discovered that it's there is Visual Studio but not the Express Editions.

Just wanted to share.

I mean Really....

Honestly, though.

Who checks in breaking changes 10 minutes before going-home time, eh?

Just wanted to share.

Friday, January 13, 2006

In the midnight hour...

She may well have cried 'More, More, More', but that's beside the point.

The point is I have more Live Messenger Beta invitations to give away.

As before, mail me here if you want one.

Saturday, January 07, 2006


Just in case anyone actually visits this blog 'in person' (rather than subscribing to the feed) the comments seem to be on the blink at the moment.

If they're not sorted out shortly, I think I might move back to Blogger's native commenting system. It's been made much better since I first moved aaway from it all those many moons ago...

If you don't visit the blog itself (You're not missing much. I really need to have a sit down and redesign it) then ignore this post.

Anyone for Windows Live Messenger 8.0?

I have a some invitations to the Windows Live Messenger 8.0 Beta.

mail me here if you're interested.

Just want to share.

Thursday, January 05, 2006

Quick thought before bed

I've heard it said that the biggest security hole in any system is the one between the keyboard and the chair. People (or at least a lot of people) need to be kinda protected from themselves. Particularly when it comes to 'all that technical stuff' like computers. Which is a shame, considering how ubiquitous they've become.

Here's a really tiny thought, but one that only occurred to me today.

Would it really be that hard to have a header or a flag or something on a web page that told the browser that under no circumstances should they cache, autocomplete, or in any way retain on the computer and values put into a form?

Just occurred to me today when Firefox autocompleted my bank details and password when I was paying some bills online.

Don't get me wrong, most of the websites I go to that need authentication have their username and passwords autocompleted. I love it. I'm even right down with Firefox's domain-level password remembering stuff (so if your site of choice puts its session ID in the URL, it'll still complete your details). But there are just some places that I really don't want to be able to do it, event if I wanted to!

PS - Yes, it's fixed now. I was in a rush one time to see my bank statement for various reasons, working on a brand new machine that I hadn't configured yet, so that's why all the details were there. But very few people I know even know how to clear their saved passwords.

Just wanted to share. I'm off to bed.

Monday, January 02, 2006

Well whaddya know?

If you type something into the address bar in Internet Explorer and hit ctrl+enter, it forms a complete .com URL from that word, so enter 'microsoft' and hit ctrl+enter and it'll complete it to 'http://www.microsoft.com'.

This is not new. It's been there for donkey's years, and it even got through to Firefox.

However, Firefox took it one step further.

FF completes the addresses with the following top-level-domain extensions:

Key comboSuffix

Who knows - there may even be more. I just haven't found them yet, though.

Discovered it on the last day I was at work before christmas. Been running round like a madman since then, though. I'll be glad to get back into the office for a break!

Anyway, hope y'all had a good one.

Just wanted to share.