C# DBNull 和可为空类型 - 最干净的转换形式
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1706405/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
C# DBNull and nullable Types - cleanest form of conversion
提问by
I have a DataTable, which has a number of columns. Some of those columns are nullable.
我有一个 DataTable,它有许多列。其中一些列可以为空。
DataTable dt; // Value set.
DataRow dr; // Value set.
// dr["A"] is populated from T-SQL column defined as: int NULL
What, then, is the cleanest form of converting from a value in a DataRow, to a nullable variable.
那么,从 DataRow 中的值转换为可为空变量的最简洁的形式是什么。
Ideally, I would be able to do something like:
理想情况下,我将能够执行以下操作:
int? a = dr["A"] as int?;
Edit: Turns out you CAN do this, the side effect being that if your Schema types arn't ints, then this is ALWAYS going to return null. The answer by Ruben of using dr.Field<int?>("A")
ensures type mismatches don't silently fail. This, of course, will be picked up by thorough unit tests.
编辑:原来你可以这样做,副作用是如果你的架构类型不是整数,那么这总是会返回空值。Ruben 对 using 的回答dr.Field<int?>("A")
确保类型不匹配不会无声地失败。当然,这将通过彻底的单元测试来实现。
Instead I'm usually typing something along the lines of:
相反,我通常会输入以下内容:
int? a = dr["A"] != DBNull.Value ? (int)dr["A"] : 0;
This is a bunch more keystrokes, but more importantly, there's more room for someone to stuff something up with a wrong keystroke. Yes, a Unit Test will pick this up, but I'd rather stop it altogether.
这是更多的按键,但更重要的是,有人有更多的空间用错误的按键来填充某些东西。是的,单元测试会解决这个问题,但我宁愿完全停止它。
What is the cleanest, least error-prone pattern for this situation.
在这种情况下,最干净、最不容易出错的模式是什么?
采纳答案by Ruben Bartelink
The LINQ to DataSets chapter of LINQ in Actionis a good read.
LINQ in Action 的 LINQ to DataSets 一章很好读。
One thing you'll see is the Field<T>
extension method, which is used as follows:-
您将看到的一件事是Field<T>
扩展方法,其用法如下:-
int? x = dr.Field<int?>( "Field" );
Or
或者
int y = dr.Field<int?>( "Field" ) ?? 0;
Or
或者
var z = dr.Field<int?>( "Field" );
回答by bniwredyc
int? a = (int?)dr["A"]
回答by stepanian
Why not use LINQ? It does the conversion for you.
为什么不使用 LINQ?它为您进行转换。
回答by Brannon
Extension methods!
扩展方法!
Something like the following:
类似于以下内容:
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;
}
}
Use it like so:
像这样使用它:
int? a = dr.GetNullableValue<int>("A");
or
或者
string b = dr.GetValue<string>("B");
回答by KM?n
Following would work, safely:
以下将工作,安全:
Snip:
剪辑:
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;
}
}
Usage:
用法:
SqlDataReaderEx.TryParse(drReader, "MyColumnName", -1);
回答by Robert Rossney
This is the purpose of the DataRowExtensions
class in .NET 3.5, which provides static Field<T>
and SetField<T>
methods for round-tripping nullable (and non-nullable) data between the DataRow
and .NET types.
这是DataRowExtensions
.NET 3.5 中类的用途,它提供静态Field<T>
和SetField<T>
方法,用于在DataRow
和 .NET 类型之间往返可空(和不可空)数据。
int? fld = row.Field<int?>("ColumnA")
will set fld
to null
if row["ColumnA"]
contains DBNull.Value
, to its value if it contains an integer, and throw an exception if it contains anything else. And on the way back,
将设置fld
为null
if row["ColumnA"]
contains DBNull.Value
,如果它包含一个整数则设置为它的值,如果它包含其他任何内容则抛出异常。而在回来的路上,
row.SetField("ColumnA", fld);
does the same thing in reverse: if fld
contains null
, it sets row["ColumnA"]
to DBNull.Value
, and otherwise sets it to the value of fld
.
反过来做同样的事情:如果fld
contains null
,则设置row["ColumnA"]
为DBNull.Value
,否则将其设置为 的值fld
。
There are overloads of Field
and SetField
for all of the value types that DataRow
supports (including non-nullable types), so you can use the same mechanism for getting and setting fields irrespective their data type.
还有的过载Field
,并SetField
为所有的值类型的DataRow
支持(包括非可空类型),所以你可以使用相同的机制来获取和设置领域,不论其数据类型。
回答by Nilesh S
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();
回答by Chetan Mandhania
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;
}
To call the function you could write
要调用您可以编写的函数
var dt = new DataTable();
dt.Columns.Add("ColumnName");
....
Add rows in Datatable.
....
dt.Rows[0].GetColumnValue("ColumnName);