tags:

views:

403

answers:

7

Hi all,

Is there a better way to write this code..

MyObject pymt = new MyObject();
pymt.xcol1id= Convert.IsDBNull(row["col1id"]) ? 0 : (int)row["col1id"];
pymt.xcold2id= Convert.IsDBNull(row["col2id"]) ? String.Empty : (string)row["col2id"];
pymt.xcold3id = Convert.IsDBNull(row["CustNum"]) ? 0 : (decimal)row["xcold3id"];

could this be done in a cleaner way .. like generic methods etc??

+1  A: 
 static ToType GenericConvert<ToType>(object value)
        {
            ToType convValue = default(ToType);

            if (!Convert.IsDBNull(value))
                convValue = (ToType)value;

            return convValue;
        }


MyObject pymt = new MyObject();
pymt.xcol1id= GenericConvert<int>(row["col1id"]);
pymt.xcold2id= GenericConvert<string>(row["col2id"]) ?? String.Empty;
pymt.xcold3id = GenericConvert<decimal>(row["CustNum"]);
Stan R.
Note that default(string) is not String.Empty, but null...
Guffa
@Guffa, forgot about that, fixed the code.
Stan R.
A: 

I actually like that. Our team had been using if/else statements which are more difficult to read in my opinion.

if (row["col1id"] == dbnull.value)
   pymt.xcol1id = 0;
else
   pymt.xcol1id = (int)row["col1id"];

Your code is easier to read because it places each assignment on individual lines.

A function as suggested by Stan might make the lines shorter but it hides the fact that nulls are being replaced unless you give it a very verbose name.

Mayo
+4  A: 

You could make generic extension methods like this:

public static class DataRowExtensions {

   public static T GetValueOrDefault<T>(this DataRow row, string key) {
      return row.GetValueOrDefault(key, default(T));
   }

   public static T GetValueOrDefault<T>(this DataRow row, string key, T defaultValue) {
      if (row.IsNull(key)) {
         return defaultValue;
      } else {
         return (T)row[key];
      }
   }

}

Usage:

MyObject pymt = new MyObject();
pymt.xcol1id = row.GetValueOrDefault<int>("col1id");
pymt.xcold2id = row.GetValueOrDefault<string>("col2id", String.Empty);
pymt.xcold3id = row.GetValueOrDefault<int>("CustNum"]);
Guffa
doh! beat me to the punch.
Brannon
+1 your implementation is better than mine, I address mine to fix what you mentioned. but now it looks dirty :(
Stan R.
I decided to use this approach because I am using VS2005, .net 2.0 version. Thank you all for your input, I very much appreciate it...
dotnet-practitioner
+3  A: 

I tend to use the null coalescing operator in situations like those. Also, DBNull.ToString returns string.Empty, so you don't have to do anything fancy there.

MyObject pymt = new MyObject();
pymt.xcol1id= row["col1id"] as int? ?? 0;
pymt.xcold2id= row["col2id"].ToString();
pymt.xcold3id = row["CustNum"] as decimal? ?? 0;
bdukes
+1 I was going to write this initially, but decided to write a GenericConvert.
Stan R.
This won't work if the property you're setting is an int and not an int? will it?
Max Schmeling
it will, because the compiler realizes that there is no way that a null will be set.
Stan R.
While this works, I suspect the methods provided in System.Data.DataSetExtensions.dll are more efficient, as Reflector shows me a fair bit of code aimed at un-boxing value types efficiently in that assembly. To be fair, I haven't run any benchmarks to compare the two approaches.
Joel Mueller
A: 

Some alternatives I can quickly think of:

  1. Strongly typed datasets
  2. Use the SqlTypes readers like ReadSqlInt32 since they all implement INullable.
  3. Generate the code with XSLT transformation from XML, so the checking code is easy to change and maintain.
Remus Rusanu
+2  A: 

Better yet, add it as an extension method to the DataRow:

static T GetValueOrDefault<T>(this DataRow row, string columnName)
{
    if (!row.IsNull(columnName))
    {
        // Might want to support type conversion using Convert.ChangeType().
        return (T)row[columnName]
    }

    return default(T);
}

You can use it like:

pymt.xcol1id = row.GetValueOrDefault<int>("col1id");
pymt.xcol2id = row.GetValueOrDefault<string>("col2id");
pymt.xcol3id = row.GetValueOrDefault<decimal>("col3id");
Brannon
Note that default(string) is not String.Empty, but null...
Guffa
Good point. Your answer is more complete, better to up-vote your answer than to further add to the noise.
Brannon
+3  A: 

Absolutely there's a cleaner way to write that code if you're using .NET 3.5, and without re-inventing extension methods that Microsoft already wrote for you. Just add a reference to System.Data.DataSetExtensions.dll, and you'll be able to do this:

MyObject pymt = new MyObject
                {
                    xcol1id = row.Field<int?>("col1id") ?? 0,
                    xcol2id = row.Field<string>("col2id") ?? String.Empty,
                    xcol3id = row.Field<decimal?>("col3id") ?? 0M
                };
Joel Mueller