Mad Props!

Omniscience is just a Google-search away.

Login

You're reading Mabsterama, the weblog of Matt Hamilton. Enjoy your stay.

SQL Collation Made Easy

In what seems to be a common theme in my posts, here's a snippet of information that everyone probably already knows but I just learned about.

Have you ever had two tables you're trying to join in a query using text-based columns (eg varchar), but they're different collations so you get a "Cannot resolve the collation conflict" error when you run the query? Whenever I got that error I used to copy the database's collation name to the clipboard and paste it into the query. Inevitably it'd be something very ugly like, "SQL_Latin1_General_CP1_CI_AS" and make the query damn-near unreadable.

Well, I just learned that the "collate" keyword accepts a special value: "database_default". You can chuck "collate database_default" after one of your varchar column references and everything's dandy! Better still, that query becomes portable - if someone else used a script to create a copy of your database on their server with a different collation, the query will still run.

Wish I'd known about this one a few years ago when we had two databases talking to each other with different collations - it would have simplified those SQL statements a lot.

Mayk's Photos

As well as being a network support guy, my workmate Mike is a photographer. I've just discovered his flickr collection. There are some really nice shots in there. Check it out!

Malware and Bloatware

I had a work trip out to Bendigo yesterday, and since my brother's place (in Shepparton) is on the way, I thought I'd pop in for a visit.

While there, I did the obligatory family-IT-support thing and took a look at his PC. It's a relatively new Dell desktop PC running Vista Home Basic. As I've said before, I always spend an hour or two stripping off all the crud that Dell pre-installs when I get a machine from them, and Ben's PC was no exception. When I gave it to him it was running the bare minimum that he needed.

The first thing I noticed was that somehow Google Toolbar had managed to reinstall itself. The second thing I noticed were some new desktop icons - one for Adobe Acrobat Reader, and another for some sort of Adobe photo album software.

Ben informed me that he'd been sent a PDF file and a link to download the reader. The other stuff must have been installed by default when he downloaded and installed the reader.

What is it with software developers nowadays and their bloatware installations? Is it not enough that a user installs Adobe Acrobat Reader without also installing Google Toolbar and some superfluous photo album software? What's in it for you, Adobe, to clutter your users' machines with this crap?

It's not limited to the corporate world, either. I updated to the latest DivX codec the other day, and the installation actually prompted me to install FireFox and the Google Toolbar!!! WTF? All I want is a freaking video codec and you're going to install an entire new browser onto my system? And this option was checked by default!!!

So Adobe Reader is no longer on Ben's machine. I replaced it with Foxit Reader which is a much better piece of software.

The other problem Ben has had is a very strange one. He can't download files from microsoft.com's download site. For example, he visits the page for the Excel Viewer and clicks the "Download" button. A small pop-up window appears, which should be where the download begins from. That pop-up ends up showing a "page cannot be displayed" error, while the original browser window navigates to the "thanks for downloading" page.

I signed in as myself and tried it, and that's where I saw a really scary message. When I clicked on the "Download" button, IE prompted me to open a new window in non-protected mode because "igfxsrvc.exe" requires it. What the hell? I searched on the net for this particular executable, and it's supposed to be a video driver for the Intel chipset on that machine. No doubt some sort of malware has installed itself onto his machine with that filename. He really needs to get some sort of malware protection other than the built-in Windows Defender.

Family IT support, huh? Fun for the whole family except for the IT guy. :)

Community Server 2007 - Easiest Upgrade Ever!

Welcome to the new-look Mad Props! As you can see, I have given the whole site a bit of a makeover, care of the new theme capabilities of Community Server 2007.

I have to say that the upgrade to CS 2007 was the simplest yet. A database upgrade script that actually worked! Who'da thunk it? The new theme system (code name Chameleon) is awesome, too. Good work, guys!

You might have noticed that my navigation bar now has a single "Blog" link instead of a "Blogs" link. That'll take you directly to Mabsterama, because I'm in the process of stripping back madprops.org to be a personal site rather than a shared one. If you still read some of the other blogs on this site, never fear - their original URLs still work.

What do you think of the site/blog theme? I really like it. It's simpler and more visually-appealing than the old one.

Anyway ... it's a new world! Enjoy!

More Than Meets the Eye

Courtesy of Geek CheckHome-made Transformers Costumes! I love the fact that they actually transform!

Not a LAN

I'm sure there are a few people waking up a bit seedy this morning after yesterday's "gaming party" at my place.

We've decided not to refer to it as a LAN party, since the PC gaming wasn't the highlight. Instead, the best games we played were table-top board games. Specifically Settlers of Catan and Carcassonne. Both turned out to be lots of fun, and I wish we'd started playing them earlier, rather than wasting time setting up PCs.

We also got to experience Guitar Hero II on the 360, thanks to Crucible. This turned out to be a lot harder than I think anybody expected, but also tonnes of fun.

Some pics from late in the night:

 

With any luck the board-game idea will take off and we'll be able to play 'em more regularly. I really enjoyed them. Not as much, apparently, as Euan enjoys UNO, but still - can't wait to try again.

AWDNUG June

Last night was our June meeting of the Albury/Wodonga .NET User Group, and since Anthony was away at a conference (meaning he'll have to give his Code Generation presentation next month) I filled in with "WPF - A Noob's Eye View".

The idea was to take a lot of the stuff I've learned over the last ten weeks of playing with WPF, and use it to give the guys a very brief introduction to the framework. I deliberately didn't prepare anything except an object model to code against (I used my Comicster.ObjectModel.dll file with its pre-existing classes), and made sure I had a full keyboard with me so I could type fast enough to not bore people.

Since I haven't installed any of the Expression tools or the Orcas CTP, I've been doing all my WPF coding in the raw XML in Visual Studio. I think it's a good way to learn what's happening "under the hood" and will serve me well when the tools mature. My introduction last night, therefore, was all XAML. I think it may have confused one or two people who have never thought about what happens behind the scenes when they visually design a form. That visual layout has to be stored somewhere - I guess most people don't think about it.

I started off by adding a few ListBox controls to a Grid in a form, and manually adding items to one of them. I then added an ObjectDataProvider and told it to call a method on a class I would write, which would get me some data to bind to. Nothing fancy - just created some Publisher objects in memory. From there we walked through binding one of the lists to that collection of publishers, and using a DataTemplate to control how each ListBoxItem was displayed.

I ended up briefly covering a few aspects of data binding (including binding to elements within the same window), templates, styles ... even touched on the idea of IValueConverters and ValidationRules.

I hope everyone found the presentation informative. I got ahead of myself a few times and had to backtrack, which is a good way of confusing your audience.

I'm now really looking forward to the code generation stuff next month. See you there!

A Dumb Suggestion for SQL Management Studio

Because the SQL Server dev team at Microsoft don't have enough to do, I present you with a really silly suggestion that would make my life just that little bit easier:

@@clipboard

I want a special variable (it only needs to work within SQL Server Management Studio) that lets me interact with the clipboard, so I could have queries in separate windows talk to each other, like this:

Window1:

SELECT TOP 1 @@clipboard = EmpID FROM Employees

Windows 2:

SELECT * FROM Orders WHERE EmpID = @@clipboard

Yes, this is a contrived example. Yes, there are ways to get around it. Yes, it only saves me a Ctrl+C and a Ctrl+V. I don't care! :)

Obviously the type of @@clipboard would need to be varbinary(max) or something, and therefore I'd have to cast or convert it in my queries. Still ... I think this would be pretty funky. Perhaps in SQL Server 2011. :)

A Nullable DateTime IValueConverter and ValidationRule

Hey guys,

So I'm designing my issue editing form in the WPF version of Comicster, and one of the fields you can edit is the release date of the issue. Thing is, if you don't know (or don't care) what the release date is, you can leave it blank. The property itself is a Nullable DateTime, so it doesn't store any value if you don't supply one.

The problem is that the default binding between a DateTime (even a nullable one) and a TextBox in WPF doesn't allow you to leave the text empty! It wants you to enter a valid DateTime value.

So the first step was to create an IValueConverter which could convert between DateTime and String, but return null if the string is empty. No sweat.

The next problem, as outlined by living legend Douglas Stockwell here, is that any exceptions raised from a custom IValueConverter aren't caught by the built-in ExceptionValidationRule. So if you enter "fred" in my TextBox, the whole program crashes and burns. Not ideal. The only solution Douglas found (and it's a good one IMHO) is to use your IValueConverter as a ValidationRule too.

With that working, I added a few little niceties to the code. So now you can type "today", "now", "yesterday" and "tomorrow" into the TextBox and they'll parse correctly. I'm still considering allowing values like "Monday" and returning the date of the most recent Monday, but I want that to be culture-dependent so I'm not doing it just yet.

Anyway, here's the code! Enjoy!

class NullableDateTimeConverter : ValidationRule, IValueConverter
{
    public override ValidationResult Validate(object value, CultureInfo cultureInfo)
    {
        if (value == null || value.ToString().Trim().Length == 0) return null;

        return new ValidationResult( 
            ConvertBack(value, typeof(DateTime?), null, cultureInfo) != DependencyProperty.UnsetValue,
            "Please enter a valid date, or leave this value blank");
    }

    #region IValueConverter Members
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        if (value == null) return "";
        DateTime? dt = value as DateTime?;
        if (dt.HasValue)
        {
            return parameter == null ? dt.Value.ToString() : dt.Value.ToString(parameter.ToString());
        }
        return ""; 
    } 

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        if (value == null || value.ToString().Trim().Length == 0) return null;
        string s = value.ToString();

        if (s.CompareTo("today") == 0) return DateTime.Today;
        if (s.CompareTo("now") == 0) return DateTime.Now;
        if (s.CompareTo("yesterday") == 0) return DateTime.Today.AddDays(-1);
        if (s.CompareTo("tomorrow") == 0) return DateTime.Today.AddDays(1);

        DateTime dt; 
        if (DateTime.TryParse(value.ToString(), out dt)) return dt; 

        return DependencyProperty.UnsetValue; 
    }  
    #endregion
} 

 

The System.ServiceModel.Syndication Namespace

Daniel Crowley-Wilson writes

I'm working on a WCF in Orcas presentation, and I just stumbled across a really easy way to consume RSS/Atom feeds. The assembly is used to generate feeds, but it can also be used to consume them. It doesn't have to be a WCF application.

He also gives us some code to consume an RSS feed! This is great stuff - I had no idea that there was such strong support for RSS in .NET 3.0!

Update! No wonder I had no idea! It's not in .NET 3.0! It's part of the Orcas (.NET 3.5) release. Guess I'll have to wait a while before I introduce this into production code. :)