我经常在处理从SqlDataAdapters返回的DataRows遇到问题。 当我尝试使用如下代码填充对象时:

DataRow row = ds.Tables[0].Rows[0];
string value = (string)row;

在这种情况下处理DBNull's最佳方法是什么。

===============>>#1 票数:36 已采纳

可空类型很好,但仅适用于不可开头的类型。

要使类型“可为空”,请在类型中附加问号,例如:

int? value = 5;

我还建议使用“ as ”关键字而不是强制转换。 您只能在可空类型上使用“as”关键字,因此请确保您正在构建已经可以为空的内容(如字符串),或者使用如上所述的可空类型。 对此的推理是

  1. 如果类型可以为空,则如果值为DBNull ,则“ as ”关键字将返回null
  2. 尽管只是在某些情况下,比铸造速度快得多 这对自己是不是一个好足够的理由来使用as ,但是加上上面是非常有用的原因。

我建议做这样的事情

DataRow row = ds.Tables[0].Rows[0];
string value = row as string;

在上面的例子中,如果row返回为DBNull ,则value将变为null而不是抛出异常。 请注意,如果您的数据库查询更改了返回的列/类型,则使用as会导致代码无提示失败并使值简单为null而不是在返回不正确的数据时抛出相应的异常,因此建议您进行测试以其他方式验证您的查询,以确保您的代码库发展时的数据完整性。

===============>>#2 票数:21

如果您没有使用可空类型,最好的办法是检查列的值是否为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类型的人工作,那么代码示例就可以解决问题。

===============>>#3 票数:8

添加对System.Data.DataSetExtensions的引用,该引用添加了Linq对查询数据表的支持。

这将是这样的:

string value = (
    from row in ds.Tables[0].Rows
    select row.Field<string>(0) ).FirstOrDefault();

===============>>#4 票数:8

我总是使用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"]);

===============>>#5 票数:5

如果您可以控制返回结果的查询,则可以使用ISNULL()返回非空值,如下所示:

SELECT 
  ISNULL(name,'') AS name
  ,ISNULL(age, 0) AS age
FROM 
  names

如果您的情况可以容忍这些魔术值替换为NULL,那么采用这种方法可以解决整个应用程序中的问题,而不会使代码混乱。

===============>>#6 票数:3

值得一提的是, 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);

===============>>#7 票数:3

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

我想这是你正在寻找的最佳实践

===============>>#8 票数:2

通常在使用DataTables时你必须处理这种情况,其中row字段可以是null或DBNull,通常我会像这样处理:

string myValue = (myDataTable.Rows[i]["MyDbNullableField"] as string) ?? string.Empty;

'as'运算符为无效的强制转换返回null,比如DBNull为string,'??' 如果第一个为null,则将该项返回到表达式的右侧。

===============>>#9 票数:1

您还应该查看扩展方法。 以下是一些处理此场景的示例。

推荐阅读

===============>>#10 票数:1

您还可以使用Convert.IsDBNull(MSDN)进行测试。

===============>>#11 票数:1

我通常编写自己的ConvertDBNull类来包装内置的Convert类。 如果值为DBNull,则它将返回null(如果是引用类型)或默认值(如果是值类型)。 示例: - ConvertDBNull.ToInt64(object obj)返回Convert.ToInt64(obj)除非obj是DBNull,在这种情况下它将返回0。

===============>>#12 票数:1

出于某种原因,我在对DBNull.Value进行检查时遇到了问题,所以我做了一些稍微不同的事情,并在DataRow对象中利用了一个属性:

if (row.IsNull["fooColumn"])
{
   value = string.Empty();
}
{
else
{
   value = row["fooColumn"].ToString;
}

===============>>#13 票数:1

几天前,布拉德艾布拉姆斯发布了相关信息http://blogs.msdn.com/brada/archive/2009/02/09/framework-design-guidelines-system-dbnull.aspx

在摘要“AVOID using System.DBNull。Prefer Nullable”。

这是我的两分钱(未经测试的代码:))

// 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的原因?

===============>>#14 票数:0

如果您担心在期望字符串时获取DBNull,则可以选择将DataTable中的所有DBNull值转换为空字符串。

这样做非常简单,但它会增加一些开销,尤其是在处理大型DataTable时。 如果您有兴趣,请查看显示如何操作的链接

  ask by Mykroft translate from so

未解决问题?本站智能推荐:

3回复

在.net / sql server中处理bc日期的最佳方法是什么?

我打算创建一个时间线应用程序来存储和显示特定日期的信息。 例如:亚里士多德公元前384年 - 公元前322年; 还有伊曼纽尔康德的广告日期22.04.1724 - 12.02.1804)。 我想使用sql compact edition数据库。 日期时间格式允许日期为1/1/1753
1回复

从DataAdapter提取数据时如何处理DBNull

我已经将MSSQL数据集导入到Visual Studio的数据集设计器中,但是在处理非空类型时遇到了麻烦。 我的数据库允许使用空整数(如果可能的话,我希望保持这种状态),但是.NET中的整数不能为空。 我想在.NET中使用可为空的整数,但该数据类型似乎不是DataSet Designer的D
5回复

实施搜索的最佳方法是什么?

我有一个要求,即用户在搜索框中输入几个词并单击“开始”。 是否有人在如何实现跨越几个数据库表的动态搜索方面有任何好的资源? 谢谢,迈克
1回复

处理DBnull执行的最佳方法是什么? [重复]

这个问题已经在这里有了答案: SQL Data Reader-处理Null列值 26个答案 我有一些返回DBnull的项目从数据库中抛出异常。 处理异常的最佳方法是什么? 更具体地说,适用于Daily和EndDate。 Daily是sql中的一位数据类型,En
3回复

使用SqlBulkCopy填充非常大的表的最佳方法是什么?

每晚,我需要从ODBC源中填充超过800万条记录来填充SQL Server 2005表。 目前,我正在从链接服务器使用插入语句,其语法选择类似于以下内容: 这确实效率低下,并且需要数小时才能运行。 我正在使用类似于此问题中发现的SqlBulkInsert代码编写解决方案的代码。
3回复

制作表格行的多个版本((或历史记录))的最佳方法是什么

嗨,大家好, 我正在尝试使我的应用程序支持日志记录,但是这种方法对我来说是新手。 我要为要支持记录的每个表向数据库中添加新表,然后通过DAL“ EF in my approach”处理该表。 但这将使我在DB和DAL方面都增加很多工作。 所以我想知道是否有更
3回复

基于关联计算表中行之间相似度的最佳方法是什么?

假设每个人都有收藏的书籍。 所以我有一张桌子: 人 书 人与书之间的关联(MxN的联合表) 我想根据喜欢的书籍重叠来获取类似于Person1的Persons。 就是说:他们拥有的共同之处越多,它们之间的相似性就越高。 我不必仅使用SQL来解决此问题
4回复

用户处理数据时,在SQL中锁定行的正确方法是什么?

我目前正在开发某种ERP,例如将SQL Server作为数据库的WPF应用程序。 到目前为止,我只需要处理不需要在服务器端锁定行的小任务。 因此,最基本的是“在数据表中创建SQLConnection->选择数据->关闭连接”。 现在,我想创建用于订单的功能。 在用
1回复

在多个项目中重用数据库访问以确保更新后不会破坏任何项目的最佳方法是什么?

我可能在多个项目中以4-5次编写相同的LINQ to SQL语句。 我什至不想粘贴它。 我们将DBML文件与Repository类结合使用。 我想在多个项目中共享同一个库,但是我也想轻松地对其进行更新,并确保它不会破坏任何项目。 什么是这样做的好方法? 如果必须更改我的方法就可以了,我
3回复

使用预加载的Sql Server Express数据库发布C#应用程序的最佳方法是什么

我想将C#应用程序与SQL Server Express 2005和应用程序对应的数据库一起分发。 安装后,SQL Server Express 2005需要在示例数据库中自动加载数据,而不仅仅是表结构。 我该怎么做。 有没有办法使用Visual Studio单击一次技术来做到这一点?