Friday, July 27, 2012

Dealing with DataSet’s Outdated Nullability Model

The DataSet is one of the most ancient relics of the .NET framework. DataSets were designed before the invention of Nullable<T> and came up with a different way to deal with database null values. So we are stuck with properties that throw StrongTypingException when the property is null and special IsXXXNull() methods to test whether a property is null. So you end up with ugly code like this:

if (!row.IsReportsToNull())
{
Console.WriteLine(row.ReportsTo);
}
else
{
Console.WriteLine("NULL");
}

or

try
{
Console.WriteLine(row.ReportsTo);
}
catch (StrongTypingException)
{
Console.WriteLine("NULL");
}

This code dance is necessary because you can’t even touch a null property without triggering an exception. So you can’t pass the property to a method that would check for nullability. But you can pass a Func<T> to a lamda:

private string GetStringForTFromDataRowField<T>(Func<bool> isNull, Func<T> getValue, 
string formatString = "{0}")
{
if (!isNull())
{
return string.Format(formatString, getValue());
}
else
{
return "NULL";
}
}

With this function I can reference the field in one (ugly) statement:

Console.WriteLine(GetStringForTFromDataRowField(row.IsReportsToNull, 
() => { return row.ReportsTo; }));

Here I am not referencing the actual property until I confirm that the property isn’t null. Since the property is referenced in an anonymous method it isn’t evaluated until after the IsNull() method confirms that the value isn’t null.

What do I get? Slightly cleaner code, I guess. You still need to match the property with the correct IsXXXNull() method. I find the code in the first couple of examples so ugly that this hack is worth the effort for me.

No comments: