Saturday, May 10, 2008

DBNull is my Nemisis

Despite what I told interviewers when looking for a new job last summer, I definitely prefer C# over Java. Having learned to program mostly in C++ with all it's (dangerous) flexibility, the fact that Java did not implicitly convert primitives to their object counter-parts (i.e. double and Double) - not to mention the endlessly long names - filled me with endless internal rage. Endless. My rage was especially acute when dealing with Java web services talking to C# web services. I'm angry just thinking about it.

C# seems to be a happy medium between the hand holding of Java and the cryptic compiler errors of C++. (Oh those compiler errors! I think fondly back on the time I continued to get a vTable error even after removing all code from the class file.) I do miss operator overloading but I generally am able to live without it ... except in one very important circumstance: DbNull.

I hate DbNull with a passion not quite reaching my hatred for no primitive/object conversion in Java but relatively close. I'm sure it's because it reminds me of dealing with this annoying aspect of Java. If you are unfamiliar with this lovely aspect of the C# language, I hope you stay blissfully ignorant and stop reading now. However, in case you've decided against ignorance, DbNull is the object that is returned when a database cell is null or, in the helpful words of MSDN, "Represents a null value." That's right. DbNull is null. Now, as a logical person, you'd think that then this statement would evaluate to true:

//where the cell in the DataRow dr is null
if(dr[0] == null) {
... do something

You'd think it would evaluate to true. You'd think that the committee of dudes (and hopefully, some ladies!) would have thought that, in this instance, we should override the Equals method and make DbNull == null always evaluate to true.

You'd think so but you'd be wrong.

This means that any time you are checking for nulls in something populated from a database, you must check for equality with DbNull.Value. I guess this is ok if everything came out of the database and was never changed, but perhaps that's not the case; perhaps some of the data is from the database and some isn't; perhaps an action such as casting with 'as' is happening on some fields. Or perhaps you'd simply like to use the ?? operator instead of less readable ? : syntax. If you want to do any of those things or if you're just a general fan of logic and non-bloated, readable code, well too bad for you. Write ugly code or scrap your idea.

So I decided to rectify this situation as best I could by writing a DbNull Utility class. I've had this idea floating around in my head ever since I first encountered this bullshit, but haven't gotten around to doing anything about it until now. On the upside, in working on this little project, I got a chance to delve a little more into C# Generics and that was exciting.

The first order of business is to write a method that checks if an object is null or DbNull:

public static bool isNull(object o)
return (o == DBNull.Value || o == null);

Easy enough.

Maybe you decide to test this out. Maybe you use ASP .Net and a datagrid because it seems like a simple utility test. Maybe you write an ItemDataBound method to change the value of a cell when it's null. Maybe you run the code and find that the value isn't changed. Then you think "What the fuck?"

Little did you know that DbNull's stupidity continues. When a DbNull value is bound to a datagrid, it's value is changed to " " I'll admit, I do understand the logic behind this on some level - it ensures that the cell renders properly in all browsers (ahem, netscape). Nevertheless, I spent many an hours trying to figure out what the hell was going on. This was back in my days of VB .Net using .Net 1.1. To make it even awesomer, converting the object to a string and checking for equality with " " didn't work. Oh no, you had to convert it to a Char Array and check for length and each element. In .Net 2.0 that no longer seems to be the case, but I've included a check for this behavior anyway. (Note: I can't remember - and am too lazy to go dig up the code - if null is bound with the trailing semi-colon or not so I check either way. Feel free to leave this out.

public static bool isNull(object o, bool webBound)
if (webBound)
string s = o as string;
if (s != null)
if (s == " ")
return true;
Char[] c = s.ToCharArray();
if ((c.Length == 5 || (c.Length == 6 && c[4] == ';')) &&
(c[0] == '&') && (c[1] == 'n') && (c[2] == 'b') && (c[3] == 's') && (c[4] == 'p'))
return true;
return isNull(o);

Since this post is getting a bit lengthy (and because I fear I'm coming off as a rage-aholic), I'm going to end this post here and continue with the methods that convert to a type in the next post.


chicagokiwi said...

Hear, hear! This *is* absolute bullshit - and for me, bullshit far more annoying that Java's lack of automatic boxing and unboxing (primitives to reference etc).

Whoever tells anyone that C# is just Java is a f*cking moron and needs their head examined.

I, too, am writing a utility class for dealing with bullshit nonsense like this - especially with DBNull.Value. But my question is - why the f*ck do developers using the framework have to do this? (Resorting to dumb utility classes)

Why the hell doesn't the framework just use null instead of a representation of null?

You know - Microsoft makes hard stuff easy, while simultaneously making everything that should be easy and intuitive, painful and laborious.

Many many many hours wasted.

Nice write up, otherwise. Just dittoing your frustration with DBNull.

becca said...

haha. i'm glad to see someone shares my pain.

i wrote this post before .net 3.5 so it *should* be a little easier and less annoying using extension methods instead of static classes.