无法将“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
值! 如果该项目为null
或DBNull.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();