0

I have the following function in C#, that I want to pass a MySQL DataReader value/object.

If the value of the object passed is a DBNull I need to handle it and return a Null value of that data type e.g null int.

Otherwise I want to convert the returned value like Convert.ToInt32(value) or similar. My function is;

public static T ConvertFromDB<T>(object value)
{
     return value == DBNull.Value ? default(T) : (T)value;
}

I can call the function like

int MyInt = ConvertFromDB(oRes["FieldName"]);

However in this case the MySQLDataReader result for oRes["FieldName"] is a DBNull, which causes a exception.

Can anyone offer any help on this ? I am using strongly typed columns, but the problem I have is if the DB value is DBNull, I need to return null of that data type e.g (int)null

neildt
  • 5,101
  • 10
  • 56
  • 107
  • 1
    "Otherwise I want to convert the returned value like Convert.ToInt32(value) or similar." - why? Why would a cast not work for you? I would expect the value fetched from the data reader to be of the right type at execution time anyway. If you've actually got numbers being stored as strings etc, I would either change that or explicitly parse them. – Jon Skeet Nov 01 '13 at 09:01
  • @JonSkeet there are times when the integer stored in db is a `short`, and a cast to `int` (assuming that's what he wants) from C# code result in invalid cast exception. `Convert.ToInt32` works fine there. – nawfal Nov 01 '13 at 15:55
  • @JonSkeet The problem I have is when using Convert.ToInt32(value), if the value is NULL I get "Data is Null. This method or property cannot be called on Null values." – neildt Nov 01 '13 at 17:07
  • @nawfal: But in those cases you could use `ConvertFromDB` and let the implicit conversion work to assign the value to an `int` variable or whatever. – Jon Skeet Nov 01 '13 at 17:09
  • @Tommo1977: My question was why you needed to use `Convert.ToInt32` at all. – Jon Skeet Nov 01 '13 at 17:09
  • @JonSkeet I'm getting the value from the DB like oRes["FieldName"], in this case a Double. So I need to Convert it ? Or Parse it ? – neildt Nov 01 '13 at 17:12
  • Cast it in a helper method, as per the method in the question - although I'd create an overload returning a `T?` for a non-nullable value type `T`. – Jon Skeet Nov 01 '13 at 17:13
  • @JonSkeet How do I create a overload returning a T? for a non-nullable value type T – neildt Nov 01 '13 at 17:18
  • Try it first (hint: you'll want `where T : struct`). Oh, and I didn't mean overload - I meant a different method name. – Jon Skeet Nov 01 '13 at 17:51
  • @JonSkeet: A separate method for Nullables shouldn't be needed, just a bit of care in advance when dealing with the possibility that they exist. – afrazier Nov 01 '13 at 17:54
  • @afrazier: To have a method like the one shown in the question, returning either a null reference or a `Nullable` value, you *do* need two methods IMO - because in one case the return type will be `T` and in the other it will be `T?`. And overloading by generic constraints doesn't work. – Jon Skeet Nov 01 '13 at 17:59
  • @JonSkeet that works, but programmers prefer to specify the type they care about when passing type arguments, and not realise what the type under the hood actually is. `foo.IntProperty = ConvertFromDB()` reads better. – nawfal Nov 01 '13 at 19:19
  • @nawfal: Not to me, personally. When there's a mismatch between my model and the database model, I'd want to make that pretty explicit. – Jon Skeet Nov 01 '13 at 20:19
  • @JonSkeet Hmm fair enough.. – nawfal Nov 02 '13 at 00:05

1 Answers1

1

Maybe you're looking for Convert.ChangeType()?

return value == DBNull.Value ? default(T) : (T) Convert.ChangeType(value, typeof(T));

Note that you're going to have to deal with exceptions when the conversion fails, which makes extension methods like this suspect.

That said, if you're reading strongly typed columns, they should already be in the format you want. Why not just use SqlDataReader.GetInt32() (or similar)? If it's because you want to refer to your DB columns by name using the SqlDataReader's index operator, maybe you'd be better off with a set of extension methods that add overloads and call GetOrdinal() within them instead. Some might argue that this is indicative of other code smells.

afrazier
  • 4,784
  • 2
  • 27
  • 30
  • @afrazier If I attempt to use SqlDataReader.GetInt32() for example when the database returns NULL, I get "Data is Null. This method or property cannot be called on Null values." – neildt Nov 01 '13 at 17:06
  • This answer worked when calling a method like ConvertFromDB(oRes["FieldName"]), that contained return value == DBNull.Value ? default(T) : (T) Convert.ChangeType(value, typeof(T)); – neildt Nov 01 '13 at 18:04