+2  A: 
int? a = (int?)dr["A"]
bniwredyc
Whether you use this or the aformentioned "int? a = dr["A"] as int?;" would be dependant on how much you trust you schema i guess.
RhysC
@RhysC: If I cant trust my schema, I want to know about it. I dont want a silent null arriving just because someone coverted my field to a sligtly different type. This way you hear about it in your tests as an exception.
Ruben Bartelink
Of course, I has the dumb. Was totally misreading what was blowing up on me!
Will Hughes
Whoops. This doesn't work if DBNull.Value is returned.
Will Hughes
+1  A: 

Why not use LINQ? It does the conversion for you.

Ralph Stevens
@Ralph: This post inspired mine. One thing to get used to around here is that a code sample speaks a thousand words in terms of votes. Nobody but me has upvoted this as you didnt expand on what you meant and assumed the questioner would figure it out from your pithy remark. (Just saying: I was in the same boat until someone pointed this out in comments to me - thanks whoever you were!)
Ruben Bartelink
Obviously I'm not holding my response in here up as a shining example of garnering deluges of votes worthy of A Horse, but you get my drift.
Ruben Bartelink
That's cool. Thanks for the advice and the vote.
Ralph Stevens
+1  A: 

Extension methods!

Something like the following:

public static class DataRowExtensions
{
    public static Nullable<T> GetNullableValue<T>(this DataRow row, string columnName)
        where T : struct
    {
        object value = row[columnName];
        if (Convert.IsDBNull(value))
            return null;

        return (Nullable<T>)value;
    }

    public static T GetValue<T>(this DataRow row, string columnName)
        where T : class
    {
        object value = row[columnName];
        if (Convert.IsDBNull(value))
            return null;

        return (T)value;
    }
}

Use it like so:

int? a = dr.GetNullableValue<int>("A");

or

string b = dr.GetValue<string>("B");
Brannon
Why would you write a set of extension methods that replicates the extension messages that the kind people at Microsoft have already written for exactly this purpose?
Robert Rossney
You're right. I forgot about LINQ to DataSet. Might as well use the built-in functionality.
Brannon
+7  A: 

The LINQ to DataSets chapter of LINQ in Action is a good read.

One thing you'll see is the Field<T> extension method, which is used as follows:-

int? x = dt.Field<int?>( "Field" );

Or

int y = dt.Field<int?>( "Field" ) ?? 0;

Or

var z = dt.Field<int?>( "Field" );
Ruben Bartelink
Fantastic. This is great. Turns out my original suggestion works too, but this has the advantage of making sure that you're not silently returning nulls because of an incorrect type spec.
Will Hughes
Ta. May I commend you on your selection :P IMNSHO `as` is definitely overused - you dont want silent nulls happening. BTW the book itself is good too - better than the APress one, though its hard to beat C# in Depth for general LINQ priming.
Ruben Bartelink
A: 

int? a = string.IsNullOrEmpty(dr["A"].ToString()) ? 0 : Convert.ToInt32(dr["A"]);

Bhaskar
This is flawed in many ways. 1. Dont depend on ToString to check for NULL. Convert can silently ignore isues 3. You're duplicating "A". I could go on. Please remove it before my my -1 urge overpowers me :P
Ruben Bartelink
Ruben i did it for you. This is not good code.
RhysC
A: 

Following would work, safely:

Snip:

public static class SqlDataReaderEx
{
    public static int TryParse(SqlDataReader drReader, string strColumn, int nDefault)
    {
        int nOrdinal = drReader.GetOrdinal(strColumn);
        if (!drReader.IsDbNull(nOrdinal))
            return drReader.GetInt32(nOrdinal);
        else
            return nDefault;
    }
}

Usage:

SqlDataReaderEx.TryParse(drReader, "MyColumnName", -1);
KMan
Thanks for the answer, but this doesn't work with the DataTable/DataRow that I already have.
Will Hughes
A: 

This is the purpose of the DataRowExtensions class in .NET 3.5, which provides static Field<T> and SetField<T> methods for round-tripping nullable (and non-nullable) data between the DataRow and .NET types.

int? fld = row.Field<int?>("ColumnA")

will set fld to null if row["ColumnA"] contains DBNull.Value, to its value if it contains an integer, and throw an exception if it contains anything else. And on the way back,

row.SetField("ColumnA", fld);

does the same thing in reverse: if fld contains null, it sets row["ColumnA"] to DBNull.Value, and otherwise sets it to the value of fld.

There are overloads of Field and SetField for all of the value types that DataRow supports (including non-nullable types), so you can use the same mechanism for getting and setting fields irrespective their data type.

Robert Rossney