无法将“System.DBNull”types的对象转换为键入“System.String”

我在我的应用程序中得到了上述错误。 这是原始代码

public string GetCustomerNumber(Guid id) { string accountNumber = (string)DBSqlHelperFactory.ExecuteScalar(connectionStringSplendidmyApp, CommandType.StoredProcedure, "GetCustomerNumber", new SqlParameter("@id", id)); return accountNumber.ToString(); } 

我换成了

 public string GetCustomerNumber(Guid id) { object accountNumber = (object)DBSqlHelperFactory.ExecuteScalar(connectionStringSplendidCRM, CommandType.StoredProcedure, "spx_GetCustomerNumber", new SqlParameter("@id", id)); if (accountNumber is System.DBNull) { return string.Empty; } else { return accountNumber.ToString(); } } 

有没有更好的方法呢?

可以使用较短的格式:

 return (accountNumber == DBNull.Value) ? string.Empty : accountNumber.ToString() 

编辑:没有注意到ExecuteScalar。 如果该字段在返回结果中不存在,它确实返回null。 那么改用:

 return (accountNumber == null) ? string.Empty : accountNumber.ToString() 

用一个简单的通用函数就可以使这个非常简单。 只要这样做:

 return ConvertFromDBVal<string>(accountNumber); 

使用function:

 public static T ConvertFromDBVal<T>(object obj) { if (obj == null || obj == DBNull.Value) { return default(T); // returns the default value for the type } else { return (T)obj; } } 

ExecuteScalar将会返回

  • 如果没有结果集,则返回null
  • 否则结果集的第一行的第一列,可能是DBNull。

如果你知道结果集的第一列是一个string,那么为了覆盖所有的base,你需要检查null和DBNull。 就像是:

 object accountNumber = ...ExecuteScalar(...); return (accountNumber == null) ? String.Empty : accountNumber.ToString(); 

上面的代码依赖于DBNull.ToString返回一个空string的事实。

如果accountNumber是另一种types(如整数),那么你需要更明确:

 object accountNumber = ...ExecuteScalar(...); return (accountNumber == null || Convert.IsDBNull(accountNumber) ? (int) accountNumber : 0; 

如果你确定你的结果集总是至less有一行(例如SELECT COUNT(*)…),那么你可以跳过检查null。

在你的情况下,错误消息“无法将types为”System.DBNull“的对象键入”System.String“,表示结果集的第一列是DBNUll值。 这是从第一行转换为string:

 string accountNumber = (string) ... ExecuteScalar(...); 

Marc_s的意见,你不需要检查DBNull.Value是错误的。

您可以使用C#的空合并运算符

 return accountNumber ?? string.Empty; 

还有另一种方法来解决这个问题。 如何修改您的商店程序? 通过使用ISNULL(你的字段,“”)sql函数,如果返回值为null,则可以返回空string。

然后你有你的干净的代码作为原始版本。

我想你可以这样做:

 string accountNumber = DBSqlHelperFactory.ExecuteScalar(...) as string; 

如果accountNumber为空,这意味着它是DBNull不是string:)

这是我用来转换任何可能是DBNull.Value的对象的通用方法:

 public static T ConvertDBNull<T>(object value, Func<object, T> conversionFunction) { return conversionFunction(value == DBNull.Value ? null : value); } 

用法:

 var result = command.ExecuteScalar(); return result.ConvertDBNull(Convert.ToInt32); 

短:

 return command .ExecuteScalar() .ConvertDBNull(Convert.ToInt32); 

String.Concat将DBNull和null值转换为空string。

 public string GetCustomerNumber(Guid id) { object accountNumber = (object)DBSqlHelperFactory.ExecuteScalar(connectionStringSplendidCRM, CommandType.StoredProcedure, "spx_GetCustomerNumber", new SqlParameter("@id", id)); return String.Concat(accountNumber); } 

不过,我认为你会在代码可理解性上失去一些东西

我使用扩展来消除这个问题,这可能是也可能不是你所追求的。

它是这样的:

 public static class Extensions { public String TrimString(this object item) { return String.Format("{0}", item).Trim(); } } 

注意:

这个扩展名不会返回null值! 如果该项目为nullDBNull.Value ,它将返回一个空string。

用法:

 public string GetCustomerNumber(Guid id) { var obj = DBSqlHelperFactory.ExecuteScalar( connectionStringSplendidmyApp, CommandType.StoredProcedure, "GetCustomerNumber", new SqlParameter("@id", id) ); return obj.TrimString(); } 

转换就好了

 string s = System.DBNull.value.ToString();