C#DBNull和可为空的types – 最简洁的转换forms

我有一个DataTable,它有很多列。 其中一些列是可空的。

DataTable dt; // Value set. DataRow dr; // Value set. // dr["A"] is populated from T-SQL column defined as: int NULL 

那么,什么是从DataRow中的值转换为可为空的variables的最简洁forms。

理想情况下,我将能够做到这样的事情:

 int? a = dr["A"] as int?; 

编辑 :原来你可以做到这一点,副作用是,如果您的架构types不是int,那么总是会返回null。 Ruben使用dr.Field<int?>("A")的答案可以确保types不匹配不会失败。 当然,这将通过彻底的unit testing来获得。

相反,我通常按照以下方式input内容:

 int? a = dr["A"] != DBNull.Value ? (int)dr["A"] : 0; 

这是一堆更多的击键,但更重要的是,有更多的空间让某个人用错误的按键来填满东西。 是的,unit testing会挑选这个,但我宁愿停下来。

什么是这种情况最干净,最不容易出错的模式。

LINQ in Action的LINQ to DataSets章节是一个很好的阅读。

有一件事你会看到是Field<T>扩展方法,使用如下:

 int? x = dr.Field<int?>( "Field" ); 

要么

 int y = dr.Field<int?>( "Field" ) ?? 0; 

要么

 var z = dr.Field<int?>( "Field" ); 

这是.NET 3.5中的DataRowExtensions类的目的,它为DataRow和.NETtypes之间的可空(不可空)数据提供了静态的Field<T>SetField<T>方法。

 int? fld = row.Field<int?>("ColumnA") 

如果row["ColumnA"]包含DBNull.Value ,则将其设置为null如果包含整数,则将其设置为其值;如果包含其他任何内容,则抛出exception。 而在回来的路上,

 row.SetField("ColumnA", fld); 

做相反的事情:如果fld包含null ,则将row["ColumnA"]DBNull.Value ,否则将其设置为fld的值。

对于DataRow支持的所有值types(包括非空types), FieldSetField都有重载,所以您可以使用相同的机制来获取和设置字段,而不考虑其数据types。

 int? a = (int?)dr["A"] 

为什么不使用LINQ? 它为你做了转换。

以下将安全地工作:

剪断:

 public static class SqlDataReaderEx { public static int TryParse(SqlDataReader drReader, string strColumn, int nDefault) { int nOrdinal = drReader.GetOrdinal(strColumn); if (!drReader.IsDbNull(nOrdinal)) return drReader.GetInt32(nOrdinal); else return nDefault; } } 

用法:

 SqlDataReaderEx.TryParse(drReader, "MyColumnName", -1); 

扩展方法!

像下面这样:

 public static class DataRowExtensions { public static Nullable<T> GetNullableValue<T>(this DataRow row, string columnName) where T : struct { object value = row[columnName]; if (Convert.IsDBNull(value)) return null; return (Nullable<T>)value; } public static T GetValue<T>(this DataRow row, string columnName) where T : class { object value = row[columnName]; if (Convert.IsDBNull(value)) return null; return (T)value; } } 

像这样使用它:

 int? a = dr.GetNullableValue<int>("A"); 

要么

 string b = dr.GetValue<string>("B"); 
 public static object GetColumnValue(this DataRow row, string columnName) { if (row.Table.Columns.Contains(columnName)) { if (row[columnName] == DBNull.Value) { if (row.Table.Columns[columnName].DataType.IsValueType) { return Activator.CreateInstance(row.Table.Columns[columnName].DataType); } else { return null; } } else { return row[columnName]; } } return null; } 

调用你可以写的函数

 var dt = new DataTable(); dt.Columns.Add("ColumnName"); .... Add rows in Datatable. .... dt.Rows[0].GetColumnValue("ColumnName); 
  Chart.data = new List < int ?> (); Chart.data = (from DataRow DR in _dtChartData.Rows select(int ? )((DR[_ColumnName] == DBNull.Value) ? (int ? ) null : (int ? ) DR[_ColumnName])).ToList();