我经常遇到处理DataRows
退回的问题SqlDataAdapters
.当我尝试使用如下代码填充对象时:
DataRow row = ds.Tables[0].Rows[0]; string value = (string)row;
DBNull's
在这种情况下处理这种情况的最佳方法是什么.
可空类型很好,但仅适用于开头不可为空的类型.
要使类型"可为空",请在类型中附加问号,例如:
int? value = 5;
我还建议使用" as
"关键字而不是强制转换.您只能在可空类型上使用"as"关键字,因此请确保您正在构建已经可以为空的内容(如字符串),或者使用如上所述的可空类型.对此的推理是
如果类型可以为空,则如果值为,则as
返回" "关键字.null
DBNull
尽管只是在某些情况下,它比铸造速度快得多.这本身就没有足够的理由使用,但加上上面的原因它很有用.as
我建议做这样的事情
DataRow row = ds.Tables[0].Rows[0]; string value = row as string;
在上面的情况下,如果row
回来DBNull
,那么value
将变为null
而不是抛出异常.请注意,如果您的数据库查询更改了要返回的列/类型,则使用as
将导致代码无提示失败并使值变得简单,null
而不是在返回不正确的数据时抛出相应的异常,因此建议您进行适当的测试以验证您的查询以其他方式确保您的代码库发展时的数据完整性.
如果您没有使用可空类型,最好的办法是检查列的值是否为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"]); }
正如Manu所说,你可以创建一个转换类,每个类型都有一个重载的转换方法,所以你不必用if/else块来代码.
但是我会强调,如果可以使用可空类型,那么它们是更好的选择.原因在于,对于非可空类型,您将不得不求助于"魔术数字"来表示null.例如,如果要将列映射到int变量,那么您将如何表示DBNull?通常你不能使用0,因为0在大多数程序中都有有效含义.我经常看到人们将DBNull映射到int.MinValue,但这也可能存在问题.我最好的建议是:
对于数据库中可以为null的列,请使用可空类型.
对于数据库中不能为null的列,请使用常规类型.
可以使用可空类型来解决这个问题.话虽这么说,如果您使用的是较旧版本的框架,或者为那些没有grok nullable类型的人工作,那么代码示例就可以解决问题.
添加System.Data.DataSetExtensions
对该查询的引用,增加了Linq对查询数据表的支持.
这将是这样的:
string value = ( from row in ds.Tables[0].Rows select row.Field(0) ).FirstOrDefault();
我总是使用If/Else检查版本,只有三元运算符才能清楚,简洁,无问题.将所有内容保留在一行中,包括如果列为空则指定默认值.
因此,假设名为"MyCol"的可为空的Int32列,如果列为null,则返回-99,但如果列不为null,则返回整数值:
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"]);
如果您可以控制返回结果的查询,则可以使用ISNULL()返回非空值,如下所示:
SELECT ISNULL(name,'') AS name ,ISNULL(age, 0) AS age FROM names
如果您的情况可以容忍这些魔术值替换为NULL,那么采用这种方法可以解决整个应用程序中的问题,而不会使代码混乱.