确定DataColumn是否为数字类型。

19

有没有比这个更好的方法来检查从SQL Server数据库中获取的DataTable中的DataColumn是否为数字?

  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
      }
    }
  }
3个回答

44

除了将类型与实际类型进行比较之外,没有好的方法来检查类型是否为数字。
特别是如果“数字的定义”有一点不同(在您的情况下,根据代码,无符号整数不是数字)。

另一件事是根据MSDN,DataColumn.DataType仅支持以下类型:

  • 布尔值
  • 字节
  • 字符
  • 日期时间
  • 十进制数
  • 双精度浮点数
  • Int16
  • Int32
  • Int64
  • SByte
  • 单精度浮点数
  • 字符串
  • 时间间隔
  • UInt16
  • UInt32
  • UInt64
  • 字节数组

加粗的类型是数字(按照我的定义),因此您需要确保对它们进行检查。

我个人会为DataColumn类型编写扩展方法(而不是TYPE!)。
我讨厌if...then..else的方式,所以我使用基于SETS的方法,像这样:

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);
}

使用方法如下:

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

这对我来说很容易


我没有包括无符号整数类型,因为它们没有列在http://msdn.microsoft.com/en-us/library/ms131092%28SQL.90%29.aspx中,但我喜欢你的方法。 - JustinStolle
1
@Dmitriy,明白了,谢谢!顺便提一下,你的代码示例中“typeof(Double)”后面缺少一个逗号。 - JustinStolle
为了针对.NET 2.0,我不得不将数组包装在ArrayList中以使用Contains方法。 - Vincent De Smet
2
@Vincent,您不需要ArrayList。您可以直接使用Array.IndexOf(numericTypes, col.DataType) != -1 - Dmytrii Nagirniak
这让我保持了一些理智!我还想指出,根据您的实现和数据源,您可能希望在第二个返回语句之前添加以下内容:if (col.DataType.IsArray) return numericTypes.Contains(col.DataType.GetElementType()); 例如,如果我有一个填充了来自查询 SQL Server 08 数据库的 ODBCDataReader 结果的 DataTable,在服务器上作为 timestamp 类型的列被转换为 DataTable 中的 System.Byte[] - p0lar_bear
显示剩余2条评论

2

另一种方法是不使用数组,只需要一行代码:

return col != null && "Byte,Decimal,Double,Int16,Int32,Int64,SByte,Single,UInt16,UInt32,UInt64,".Contains(col.DataType.Name + ",");

这行代码既可以用作普通的帮助方法,也可以用作扩展方法。


这样做非常低效!而且对于奇怪的类型,比如malnt16,是错误的。 - undefined
@MicheldeRuiter 你有测量过它的效率吗?string.Contains()非常快,可能比循环遍历数组的速度还要快!关于数据类型,虽然我们知道像nt16这样奇怪的数据类型不存在,但如果你想让代码更加健壮,你可以在开头也加上一个逗号(如编辑后的帖子中所示)。 - undefined

1

也许你可以用以下方式使它更短:

System.Type theType = col.DataType AS System.Type
if(theType  == System.Single || theType  == System.Double...) {}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接