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), Field
和SetField
都有重载,所以您可以使用相同的机制来获取和设置字段,而不考虑其数据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();