views:

945

answers:

2

Is there a better way than this to check if a DataColumn in a DataTable is numeric (coming from a SQL Server database)?

  Database db = DatabaseFactory.CreateDatabase();
  DbCommand cmd = db.GetStoredProcCommand("Get_Some_Data");
  DataSet ds = db.ExecuteDataSet(cmd);

  foreach (DataTable tbl in ds.Tables) {
    foreach (DataColumn col in tbl.Columns) {
      if (col.DataType == typeof(System.Single)
        || col.DataType == typeof(System.Double)
        || col.DataType == typeof(System.Decimal)
        || col.DataType == typeof(System.Byte)
        || col.DataType == typeof(System.Int16)
        || col.DataType == typeof(System.Int32)
        || col.DataType == typeof(System.Int64)) {
        // this column is numeric
      } else {
        // this column is not numeric
      }
    }
  }
A: 

Maybe you could make it shorter with:

System.Type theType = col.DataType AS System.Type
if(theType  == System.Single || theType  == System.Double...) {}
Jonathan
This won't even compile
Dmytrii Nagirniak
+6  A: 

There is no good way to check if the type is numeric except comparing it to the actual types.
This is especially true if the definition of numeric is a bit different (in your case, according to code, - unsigned integers are not numerics).

Another thing is that DataColumn.DataType according to MSDN only supports following types:

  • Boolean
  • Byte
  • Char
  • DateTime
  • Decimal
  • Double
  • Int16
  • Int32
  • Int64
  • SByte
  • Single
  • String
  • TimeSpan
  • UInt16
  • UInt32
  • UInt64
  • Byte[]

The bolded types are numerics (as I define it) so you need to make sure you check them.

I personally would write an extension method for the DataColumn type (not for the TYPE!).
I hate the if...then..else thing so instead I use a SETS-based approach, like this:

public static bool IsNumeric(this DataColumn col) {
  if (col == null)
    return false;
  // Make this const
  var numericTypes = new [] { typeof(Byte), typeof(Decimal), typeof(Double),
        typeof(Int16), typeof(Int32), typeof(Int64), typeof(SByte),
        typeof(Single), typeof(UInt16), typeof(UInt32), typeof(UInt64)};
  return numericTypes.Contains(col.DataType);
}

And the usage would be:

if (col.IsNumeric()) ....

which is easy enough for me

Dmytrii Nagirniak
+1 for Extension method, keeps the pain 1 place
Henk Holterman
I didn't include the unsigned integer types because they weren't listed in http://msdn.microsoft.com/en-us/library/ms131092%28SQL.90%29.aspx but I do like your approach.
JustinStolle
@JustinStolle, I would better include the unsigned types according to the MSDN page I provided. The page you reference is the SQL Server 2005 specific.
Dmytrii Nagirniak
@Dmitriy, makes sense, thank you! FYI, you are missing a comma after "typeof(Double)" in your code sample.
JustinStolle
Fixed that. That's the copy-paste's fault, not mine :)
Dmytrii Nagirniak
Targeting .NET 2.0 I had to wrap the Array in an ArrayList to use the Contains method.
Vincent
@Vincent, you don't need ArrayList. You can just do `Array.IndexOf(numericTypes, col.DataType) != -1`
Dmytrii Nagirniak