July 30, 2010

Cleaning up my data access layer with generics and extension methods

Last night Cory Fowler (@SyntaxC4) and I got to discussing helper methods to clean up database interaction for our data access layers (DALs). I'm currently working on a project where I'm having to pull large amounts of data from a SQL Server database and apply it to properties. In small batches, this isn't a problem, but something just doesn't feel right about hundreds of lines of:

if(!DBNull.Equals(reader["fieldX"]) myClass.PropertyX = 
    rdr.GetString(reader.GetOrdinal("fieldX"));

...even with the correct base classes set up to take the heavy lifting so you're only setting any given property in only one place.

Between us we managed to come up with a pretty neat generic method of just a couple of lines of code that allowed us to condense this a fair bit

public static T GetDbValue<T>(object value){
    if (!DBNull.Value.Equals(value))
        return (T)Convert.ChangeType(value, typeof(T));
    return default(T);
}

Which could also be applied as an extension in .NET 3.5 (and up)

public static class DBExtensions
{
    public static T GetDbValue<T>(this object value){
        if (!DBNull.Value.Equals(value))
            return (T)Convert.ChangeType(value, typeof(T));
        return default(T);
    }
}

And I can call it using:

myClass.PropertyX = rdr["fieldX"].GetDbValue<int32>();

Awesome! and thanks to Cory for his initial inspiration that got us started which he blogged about this morning in his post Database Safe Values, Using Generics, and Extension Methods.

This morning though, something was niggling me - I don't want this extension applying to any object. It just feels...dirty, because this is only really relevant in this form for database values (because of the DBNull). So this leaves me with 2 thoughts... do I allow this to be applied to any type of object and somehow account for the fact that database values may be DBNull and "regular values" may either be null or nullable? Or do I find a way to apply this only to IDataReader fields?

I wasn't even sure I could distinguish the difference between a generic object and a IDataReader field, and indeed, upon further investigation it seems that the IDataReader field object is just a simple generic object, which leaves no way to distinguish it from any other object... so I guess that's it, I'm stuck with that...

Then I had my morning tea...

IDataReader has a bunch of GetXXX fields already, all I'm really trying to do is mimic them, but with an additional null check [plus, I don't want different methods for each data type, that's just so... well... I just don't like it]. So why don't I just attach my extension method directly to the IDataReader, which is what it really applies to, chasing down to the field level was one level too far.

public static T GetValue<T>(this IDataReader reader, 
                            string fieldName)
{
    object value = reader[fieldName];
    if (!DbNull.Value.Equals(value))
        return (T)Convert.ChangeType(value, typeof(T));
    return default(T);
}

Sweet, now I can call it using the much more standard:

myClass.PropertyX = rdr.GetValue<int>("fieldX");

I've combined my null checking into the method so I don't have hundreds of checks coded, they're contained in the method, and it's type-safe via the wonder of generics.

All this said, I could have left it attached as an extension method to object, and just added an extra check for null to the if line:

if (value != null && !DBNull.Value.Equals(value))
    return (T)Convert.ChangeType(value, typeof(T));

This will now work with null and DBNull, so you could apply it to any object*. I think my preference is to extend IDataReader in this instance purely because I prefer the calling syntax of:

myClass.PropertyX = rdr.GetValue<int>("fieldX");
over:
myClass.PropertyX = rdr["fieldX"].GetValue<int>();

For no other reason than it just looks prettier to me. But for other scenarios, the second method may be more suitable.

Addendum:

As John pointed out, this doesn't account for true null values being passed (vs. DBNull). If a null value is passed into the method, it will crash attempting to do the conversion. In this case, a slight modification to the code is in order:

public static T GetValue<T>(this IDataReader reader, 
                            string fieldName)
{
    object value = reader[fieldName];

    if (value == null || DBNull.Value.Equals(value))
        return default(T);

    Type t = typeof(T);
    return (T)Convert.ChangeType(value, 
        Nullable.GetUnderlyingType(t) ?? t);
}

So now we should be able to translate null as well as DBNull into the correct type specified by the generic.

July 28, 2010

Apple religion - the abusive relationship that spells the end of technical objectivity

Okay, on any normal day, I wouldn't be caught dead getting sucked into any of the religious debates that are rife in the technology industry. But today, it's starting to get a bit much for me.

The technology industry used to be a community of critics, objectivity and experimentation - tinkerers who were never satisfied with the gadgets in our arsenal until we'd eked every last morsel of functionality out of them. It used to be that journalists actually understood what they were writing about, held their objectivity and clarity above all else. Today though, it seems that Apple's marketing machine [which is never anything short of impressive] has sucked the world's journalists into the techno-lust of their religion and I'm hearing press-release grade reporting on the radio. What the **** is going on with the world? We need some Larry King grade reporters in this industry to get some of this marketing BS back in check. Reporters should understand what they're reporting about!

Everywhere I look, I see articles about how Apple is the harbinger of the end of the mouse era because of their magic touch pad. I'll admit, this sleek looking silver wireless touch pad that sits so alluringly at the side of their equally sexy slimline wireless keyboard is nothing short of gorgeous, a work of art for which I must tip my hat to their hardware designers. But where has everyone's objectivity gone?

Wacom have been making tablets for years, and they too have a range, called Bamboo [check them out at http://www.wacom.com/bamboo/], which is far more versatile and in the exact same price bracket as Apple's magic pad. They've got one that's just touch, one that's just pen and one that's both and all for under $100, they support multi-touch, gestures, their pen supports pressure sensitive graphics apps and a heap of other stuff too. So why then have they not received the acclaim that Apple's getting for this... knock off?

It may indeed be that this is the beginning of the end for the mouse, but please people - get some objectivity. Apple's offerings may indeed look gorgeous [so gorgeous], they may be perfectly usable but this religious attachment to their products is impairing your ability to see through their marketing crap and realize that all they're doing is packaging ideas that are already available [in some cases for quite a while], making them look sexy [which I've gotta admit, they're really good at], making you believe they're more usable and more stable [which in many cases, they're not], marking up the price by 20-50% and telling you that their products are changing the world.

...and you're hanging on to their every word like the nerd at high school hangs on to the pretty girl's every last word in the misguided hope that one day, she'll love you back. Apple are never going to love you back, they care about two things: How much money you have, and how to get you to give it to them. So far, their marketing machine seems to have you in their clutches.

One thing I have got to concede is that Apple do have an uncanny ability to understand what the market is ready for at any given time. They have an almost surreal knack of delivering a product that's dumbed down so far as to be usable by the average 5 year old, and only crippled so far that we will still buy it despite bitter complaints. We will continue to use it, all the while complaining that it doesn't have the quite feature set we really want [AD2P/Tethering/iTunes - quite possibly the shittiest music management system ever released, their BS walled garden app store etc.] and just as we're about to leave and go somewhere that promises us a better life, they give us a few more features - just enough to keep us from leaving, but not enough that we're truly happy about it. It's a classic abusive relationship. "He says he loves me and that he's sorry and he'll never do it again. I can't leave him, how will I support my family?"