tags:

views:

205

answers:

5

When looping through a DataRow and encountering types such as

DataRow dr;
dr["someString"]
dr["someInteger"]
dr["somedata"]

What's the best way to get them into their corresponding data types? dr["foo"] is just a generic object.

Also, are these able to be easily converted to nullable types? dr["someInteger"] could be null.

+2  A: 

Simply casting the values to the right type should work:

(string) dr["someString"];
(int?) dr["someInteger"];
(byte[]) dr["somedata"];
Ronald Wildenberg
Warning, `(int?) dr["someInteger"];` will fail if the value is DBNull.
Pierre-Alain Vigeant
Is there any benefit of casting verses calling int.Parse() for example?
Gratzy
Is there a shortcut to getting (int?) to work. I'm thinking something like int?.TryParse(dr["some"]) ? (int?)dr["some"] : null
Michael Pryor
int.Parse only accepts a string as parameter, so that won't help you.
Ronald Wildenberg
+3  A: 

If you can use .net 3.5, then you can use the Field extension method to more easily access the data if you know the type. An example would be:

 string somestring= row.Field<string>("SomeString");

Otherwise you're stuck with casting the field to the type of the object the old fashioned way.

womp
I'm stuck. Thanks :)
Michael Pryor
+7  A: 

When reading from a DataRow, your biggest enemy is a null value. In a DataRow, when a value is null, it is not equals to null: It is equals to DBNull.Value.

if(DBNull.Value == null)
{
   // Will never happen
}

Unless you know that your field cannot be null, it is not safe to cast. For example, the following example will fail if the data is DBNull:

string name = (string)dr["Name"];

If you can use the LINQ extensions, you can include the reference System.Data.DataSetExtensions and the namespace System.Data and call

string name = dr.Field<string>("Name");

If you cannot use LINQ, then you have to fall back to checking for null value with

string name = null;
if(!dr.IsNull("Name"))
    name = (string)dr["Name"];

Or you could code your own Field function like this:

public static T GetValue<T>(object value)
{
    if (value == null || value == DBNull.Value)
        return default(T);
    else
        return (T)value;
}

and get your value this way:

string name = GetValue<string>(dr["Name"]);
Pierre-Alain Vigeant
What happens if you call int i = dr.Field<int>("someintcolumn"); and the row is null?
Michael Pryor
Field<T>() is bright enough to return default(T), so your i variable will be equals to 0 if the data is null.
Pierre-Alain Vigeant
+1 for thoroughness and taking the time to cover nulls.
womp
A: 
string GetString(DataRow dr, string ColumnName)
{
    if (dr.IsNull(ColumnName)) 
    {
        return null;
    }
    return (string)dr[ColumnName];
}
Daniel Mošmondor
Wouldn't it make more sense to return an empty string instead of null here?
Beavis
Maybe, but there can also be "" in column value, so you have to differentiate somehow. It depends on how you like/need it.
Daniel Mošmondor
A: 

Another option is to use "as"

string str = dr["someString"] as string;

if it's DBNull.Value (or any other object not of type string), then str will get a real "null". Otherwise it will get the proper string value.

For value types, you can use nullable, i.e.

int? i = dr["someint"] as int?;

Again, it will get a real "null" instead of DBNull.Value. However, with nullable types you have to remember to use .Value, i.e.

int x = i.Value + 5;
JoelFan
int? i = 3; int x = i + 5; won't work? Weird! Never knew that.
Michael Pryor
won't even compile
JoelFan