什么是最好的方式来处理DBNull的
我经常遇到问题处理DataRows
从SqlDataAdapters
返回。当我尝试填补对象使用这样的代码:什么是最好的方式来处理DBNull的
DataRow row = ds.Tables[0].Rows[0];
string value = (string)row;
什么是这种类型的情况来处理DBNull's
的最佳途径。
可以为空的类型是好的,但只适用于不能以空格开头的类型。
为了一种“可空”问号追加到类型,例如:
int? value = 5;
我也建议使用“as
”关键字,而不是铸造的。您只能在可为空的类型上使用“as”关键字,因此请确保您正在投射已经为空的东西(如字符串),或者使用上面提到的可空类型。这样做的原因是
- 如果一个类型是空的,则“
as
”关键字返回null
如果值是DBNull
。 - 它是ever-so-slightly faster than casting虽然only in certain cases。这本身并不是一个足够好的理由来使用
as
,但加上它的原因是有用的。
我建议你做这样的事情
DataRow row = ds.Tables[0].Rows[0];
string value = row as string;
在上述情况下,如果row
回来为DBNull
,然后value
将成为null
,而不是抛出异常。请注意,如果您的数据库查询更改了返回的列/类型,使用as
将导致您的代码在默认情况下失败并使值简单null
而不是在返回不正确的数据时抛出相应的异常,因此建议您进行测试以其他方式验证您的查询,以确保您的代码库发展时的数据完整性。
添加对System.Data.DataSetExtensions
的引用,该引用添加了Linq对查询数据表的支持。
这将是这样的:
string value = (
from row in ds.Tables[0].Rows
select row.Field<string>(0)).FirstOrDefault();
+1:这个答案应该是更upvoted大概也接受了 - 绝对row.Field
我平时写一个封装内置Convert类我自己ConvertDBNull类。如果该值为DBNull,则它将返回null(如果其引用类型)或默认值(如果其值类型)。 例子: - ConvertDBNull.ToInt64(object obj)
回报Convert.ToInt64(obj)
除非obj是为DBNull在这种情况下,如果你不使用可空类型,它将返回0。
,做的最好的事情就是检查是否该列的值是为DBNull。如果它是DBNull,那么设置你对相应的数据类型使用null/empty的引用。
DataRow row = ds.Tables[0].Rows[0];
string value;
if (row["fooColumn"] == DBNull.Value)
{
value = string.Empty;
}
else
{
value = Convert.ToString(row["fooColumn"]);
}
随着马努说,你可以创建每个类型的重载转换方法的转换类,所以你不if/else语句块必须辣椒代码。
但是我会强调,如果你可以使用它们,可以为空的类型是更好的路径。理由是,对于非空类型,您将不得不求助于“幻数”来表示空值。例如,如果你将一个列映射到一个int变量,你将如何表示DBNull?通常你不能使用0,因为在大多数程序中0有一个有效的含义。通常我会看到人们将DBNull映射到int.MinValue,但这可能也有问题。我最好的建议是这样的:
- 对于在数据库中可以为空的列,请使用可为空的类型。
- 对于数据库中不能为空的列,请使用常规类型。
可以使用可为空的类型来解决这个问题。话虽如此,如果您使用的是旧版本的框架,或者为不支持可空类型的人员工作,那么代码示例就可以解决这个问题。
行if(行[“fooColumn”] == DBNull.Value)的作品,但不正确。它没有被定义DBNull.Value应该被实现为Singleton模式。更好的一行是:if(row [“fooColumn”]是DBNull) – doekman 2009-06-12 08:30:32
@doekman - 实际上,DBNull *是一个单例类。引用MSDN:“DBNull是一个单例类,这意味着只有这个类的[DBNull.Value]实例可以存在。” http://msdn.microsoft.com/en-us/library/system.dbnull.value.aspx – Greg 2009-12-22 16:39:42
如果你想治疗的DBNull为空字符串行[“fooColumn”]。的ToString()将做到这一点。 – samir105 2012-12-23 08:27:46
出于某种原因,我已经受够了做对DBNull.Value检查的问题,所以我已经做过的事情有所差异,DataRow对象中的杠杆属性:
if (row.IsNull["fooColumn"])
{
value = string.Empty();
}
{
else
{
value = row["fooColumn"].ToString;
}
如果你有控制即返回结果的查询,你可以使用ISNULL()返回非空值是这样的:
SELECT
ISNULL(name,'') AS name
,ISNULL(age, 0) AS age
FROM
names
如果你的情况可以容忍这些魔法值代替NULL,采用这种方法可以解决这个问题通过你的整个应用程序,而不会混淆你的码。
我总是发现使用If/Else检查版本的清晰,简洁和无问题,只能使用三元运算符。将所有内容保留在一行上,包括如果列为空,则分配默认值。
因此,假设名为“MyCol”一空Int32列,在这里我们想返回-99如果列空,但返回整数值如果列不为空:
return row["MyCol"] == DBNull.Value ? -99 : Convert.ToInt32(Row["MyCol"]);
这是与上面的If/Else获胜者相同的方法 - 但是我发现,如果您从数据读取器中读取多列,这是一个真正的奖励,所有列读线都排在一起,排列整齐,因为它更容易现场错误:
Object.ID = DataReader["ID"] == DBNull.Value ? -99 : Convert.ToInt32(DataReader["ID"]);
Object.Name = DataReader["Name"] == DBNull.Value ? "None" : Convert.ToString(DataReader["Name"]);
Object.Price = DataReader["Price"] == DBNull.Value ? 0.0 : Convert.ToFloat(DataReader["Price"]);
布拉德·艾布拉姆斯发布有关短短几天前 http://blogs.msdn.com/brada/archive/2009/02/09/framework-design-guidelines-system-dbnull.aspx
总结的东西“避免使用System.DBNull。身高可空来代替。“
这里是我的两分钱(未经测试的代码:))
// Or if (row["fooColumn"] == DBNull.Value)
if (row.IsNull["fooColumn"])
{
// use a null for strings and a Nullable for value types
// if it is a value type and null is invalid throw a
// InvalidOperationException here with some descriptive text.
// or dont check for null at all and let the cast exception below bubble
value = null;
}
else
{
// do a direct cast here. dont use "as", "convert", "parse" or "tostring"
// as all of these will swallow the case where is the incorect type.
// (Unless it is a string in the DB and really do want to convert it)
value = (string)row["fooColumn"];
}
而且一个问题......你没有使用ORM的原因吗?
的DBNull实现的ToString() 。像其他一切不需要做任何事情而不是硬投,调用该对象的的ToString()方法
DataRow row = ds.Tables[0].Rows[0];
string value;
if (row["fooColumn"] == DBNull.Value)
{
value = string.Empty;
}
else
{
value = Convert.ToString(row["fooColumn"]);
}
这将成为:
DataRow row = ds.Tables[0].Rows[0];
string value = row.ToString()
DBNull.ToString()返回的String.Empty
我会想象这是你要找的
值得一提的是,这DBNull.Value.ToString()
等于String.Empty
你可以用你的优势:
DataRow row = ds.Tables[0].Rows[0];
string value = row["name"].ToString();
然而,这仅适用于弦乐,其他一切我会使用linq方式或扩展方法。至于我自己,我写了检查的DBNull一点点扩展方法,并与数据表工作时,即使不通过Convert.ChangeType(...)
int value = row.GetValueOrDefault<int>("count");
int value = row.GetValueOrDefault<int>("count", 15);
通常情况下,铸造你必须处理这种情况下,如果行字段可以是零或DBNull的,通常我处理,像这样:
string myValue = (myDataTable.Rows[i]["MyDbNullableField"] as string) ?? string.Empty;
的“为”经营者返回null无效转换的,像DBNull的字符串,而“?”如果第一个为空,则返回 表达式右侧的项。
密切:[最高效的单向到检查换的DBNull和 - 然后,分配到一个变量(http://stackoverflow.com/questions/221582/most-efficient-way -to-检查换为DBNull和-然后指派到一个变量) – nawfal 2013-12-11 16:42:38