Nullable Types are NOT Integrated in .NET v2.0

Nullable value types have been added to .NET v2.0, but they have NOT really been integrated.  The C# team has done a good job incorporating support for nullable types into the syntax, but the VB team has done nothing, which once again leaves VB behind the curve in features.  But that is not what this post is about -- this post is about the fact that nullable types have NOT been integrated into the rest of the .NET framework -- and obvious places at that.

(1) Reading Data: Given a data reader, you can't just assign a value to a nullable type!  This one just seems incomprehensible -- nullables obviously already exist in the database, and the .NET SqlTypes support them already, so this seems to be a key integration point.  But alas, you simply can NOT assign a value from your data reader to a nullable type.  Instead, you still have to explicitly test for DBNull, and handle that case separately:
 
    int? nullInt;
    if (dataReader.IsDBNull(index)) { nullInt = null; }
    else { nullInt = dataReader.GetInt32(index); }

Note that Julia Lerman observed this before -- see her comments for more viewpoints.

(2) ConvertType: C# does at least support casts to/from regular types and nullable types, and it even gives you a handy way to convert nulls to a default by using the ?? operator, but just try to do any generic type conversions with Convert.ChangeType -- not supported!  Again this seems like an obvious integration point, if nullable types are to be "builtin", but once again the new nullable types just feel like an afterthought -- and NOT integrated.

(3) WinForm Controls: The official story is that the data grids support nullable types, but what happens when you try to use a NumericUpDown or a DateTimePicker -- not supported!  That's right, once again you'll find that you still have no real integration for nulls, and you'll have to continue resorting to magic values or checkboxes and manual conversions.  These controls seem like another obvious place where there should be support for nullables.

All of this lack of integration makes me wonder what the point of nullable types really is?  We could always create our own structs that supported the concept of null very similarly, but they lacked the builtin syntax support that C# is including, not to mention they failed to work with data-binding in grids, but the new nullable types simply aren't much better.  The one thing they have going for them is that they will at least be a "standard" nullable.

Note that none of these issues prevented me from adding support for nullable types to my O/R Mapper, but I just thought I'd pass along what I observed since I do think the support I discovered was very disappointing.

13 Comments

  • Well, since the idea of nullable value types was just plain left out of a modern platform (.NET) in the beginning was incredibly bizarre to me, especially in this age of database interactivity.



    Getting nullables to be more integrated is a definitely great start to get the platform (.NET) into CURRENT standards, instead of OO-based C++ standards of 10 years ago (where Objects would serialize/deserialize locally...)



    Agreed these "irritations" with the DataReaders is annoying, and IMO the IDataReader interfaces should obviously be extended (via IDataReader2 or IDataReaderEx or something) to provide nullable types through the interface, and hence "encourages" implementing it all the way through to the SqlDataReader's implementation of

    "int? IDataReader2.GetInt32(int ordinal)"

  • Just say no to NULLS!



    Join PAN. Programmers Against Nulls!

  • It's not just IDataReader that's not supported. NONE of the System.Data classes support nullable types. Just try to use something like



    command.Parameters.AddWithValue("@SomeParam", (int?)null)



    This will throw an exception once you try to execute the command. Yet the following works:



    command.Parameters.AddWithValue("@SomeParam", SqlInt32.Null)



    There aren't even any implicit/explicit conversions between SqlTypes and Nullable types. I was baffled when I noticed that.



    It's things like this that make nullable types *really* annoying to work with when you're doing database work.



    Erm, refresh my memory, why were they added again?

  • Well, one of the major problems is the idea of NULL in the database in the first place.



    One of my major complaints about the SQL Server 2000 table design tools is that columns allow NULL by default. This is a pretty significant design decision, and I believe that NULLs should be allowed in the database only in extra-ordinary circumstances.



    However, many 'DBAs' allow null by default, and it really creates havoc.



    NULLable types are a hack to make programming against screwy database designs easier for client-side programmers.

  • Last year at Teched Europe, someone asked Dan Fernandez about nullable types and datareader... they (he and another MS guy) got that look on their face: "oh erm... whoa, we didn't think of that! we'll pass it on!". Nothing happened apparently.



    Oh, btw, DON'T use datareader.IsDBNull(..). It's very slow. Test the value for System.DBNull.Value, much faster. (magnitudes faster)



    I also find the lack of integration of nullable types a severe stupidity. I mean, int's and all ARE already structs. All it takes is another field. ONE FIELD.



    ok, you can use Nullable<T> but that's almost 50% slower. Why, I don't know, as it's just 1 flag, 1 BIT.

  • Paul,



    Wow, thanks for the headsup.



    Wally

  • WTF?

    I thought that interaction with nullable fields in the DB (such as situation #1) was the main line for nullable types in the framework. Mostly to eliminate all kinds of null checking.



    If they don't do that then why even spend the time to implement it?





    ?UsefullType

  • I don't think anyone expects them to be null -- just to be integrated with their expected uses.

  • I've been reading up on the subject...........And the impedance mismatch continues.

  • I use a simple converter for O/R mapping:

    public static class SqlTypeConverter
    {
    public static int? ToNulllableInt32(object o)
    {
    SqlInt32 i = (SqlInt32)o;
    return i.IsNull ? null : (int?)i;
    }

    ...or

    public static int? ToNullable(SqlInt32 i)
    {
    return i.IsNull ? null : (int?)i;
    }

    ... and so on ...
    }

    But, of course, this still doesn't help with the ignorant controls!

  • Here's how I get around the value in a datareader:

    if (myDataReader.GetValue(5).ToString().Length > 0)
    {
    do stuff
    }

    ive only used to to test the selected value of a dropdown list when I was populating it from the database and getting the value that had been selected by the user a previous time.

    worked like a champ.

    the reason I used that if statement was because when I tried to write that value to the page, nothing happened. So, since testing != null or != "" didnt work, I went with length

  • Check against the DBNull object, not null.

  • Although it's true that the lack of integration is annoying, the fact that I CAN now create a null-value base type is a tremendous relief. I don't mind using obscure conversion syntax at the border of the data-retrieval-layer if I don't have to pollute the rest of my code with all those ugly SqlTypes.

    Le roi est nul! Vive le roi!

Comments have been disabled for this content.