Possible to use ?? (the coalesce operator) with DB

2020-02-05 12:32发布

问题:

If I have code similar to the following:

while(myDataReader.Read())
{
  myObject.intVal = Convert.ToInt32(myDataReader["mycolumn"] ?? 0);
}

It throws the error:

Object cannot be cast from DBNull to other types.

defining intVal as a nullable int is not an option. Is there a way for me to do the above?

回答1:

Can you use an extension method? (written off the top of my head)

public static class DataReaderExtensions 
{
    public static T Read<T>(this SqlDataReader reader, string column, T defaultValue = default(T))
    {
        var value = reader[column];

        return (T)((DBNull.Value.Equals(value))
                   ? defaultValue
                   : Convert.ChangeType(value, typeof(T)));
    }
}

You'd use it like:

while(myDataReader.Read())
{
  int i = myDataReader.Read<int>("mycolumn", 0);
}


回答2:

Here's one more option:

while (myDataReader.Read())
{
    myObject.intVal = (myDataReader["mycolumn"] as int? ?? 0);
}


回答3:

Can you simply use Int32.Tryparse?

int number;
bool result = Int32.TryParse(myDataReader["mycolumn"].ToString(), out number);

According to the MSDN, number will contain 0 if the conversion failed



回答4:

How about something like:

object x = DBNull.Value;
int y = (x as Int32?).GetValueOrDefault(); //This will be 0

Or in your case:

int i = (myDataReader["mycolumn"] as Int32?).GetValueOrDefault();


回答5:

Why not use something other than the null coalescing operator (DBNull.Value != null):

int i = myDataReader["mycolumn"] == DBNull.Value ?
            Convert.ToInt32(myDataReader["mycolumn"]) :
            0;

You could always wrap it up in a neat extension method:

public static T Read<T>(this DataReader reader, string column, T defaultVal)
{
    if(reader[column] == DBNull.Value) return defaultVal;
    return Convert.ChangeType(reader[column], typeof(T));
}


回答6:

Nope, only works for nulls.

How about an extension method on object that checks for DBNull, and returns a default value instead?

//may not compile or be syntactically correct! Just the general idea.
public static object DefaultIfDBNull( this object TheObject, object DefaultValue )
{
    if( TheObject is DBNull )
        return DefaultValue;
    return TheObject;
}