Unable to cast object of type 'System.DBNull' to type 'System.String`

前端 未结 11 1712
青春惊慌失措
青春惊慌失措 2020-11-22 06:45

I got the above error in my app. Here is the original code

public string GetCustomerNumber(Guid id)
{
     string accountNumber = 
          (string)DBSqlHel         


        
相关标签:
11条回答
  • 2020-11-22 07:19

    String.Concat transforms DBNull and null values to an empty string.

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

    However, I think you lose something on code understandability

    0 讨论(0)
  • 2020-11-22 07:25

    With a simple generic function you can make this very easy. Just do this:

    return ConvertFromDBVal<string>(accountNumber);
    

    using the 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;
        }
    }
    
    0 讨论(0)
  • 2020-11-22 07:27

    ExecuteScalar will return

    • null if there is no result set
    • otherwise the first column of the first row of the resultset, which may be DBNull.

    If you know that the first column of the resultset is a string, then to cover all bases you need to check for both null and DBNull. Something like:

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

    The above code relies on the fact that DBNull.ToString returns an empty string.

    If accountNumber was another type (say integer), then you'd need to be more explicit:

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

    If you know for sure that your resultset will always have at least one row (e.g. SELECT COUNT(*)...), then you can skip the check for null.

    In your case the error message "Unable to cast object of type ‘System.DBNull’ to type ‘System.String`" indicates that the first column of your result set is a DBNUll value. This is from the cast to string on the first line:

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

    Marc_s's comment that you don't need to check for DBNull.Value is wrong.

    0 讨论(0)
  • 2020-11-22 07:29

    This is the generic method that I use to convert any object that might be a DBNull.Value:

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

    usage:

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

    shorter:

    return command
        .ExecuteScalar()
        .ConvertDBNull(Convert.ToInt32);
    
    0 讨论(0)
  • 2020-11-22 07:29

    I use an extension to eliminate this problem for me, which may or may not be what you are after.

    It goes like this:

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

    Note:

    This extension does not return null values! If the item is null or DBNull.Value, it will return an empty String.

    Usage:

    public string GetCustomerNumber(Guid id)
    {
        var obj = 
            DBSqlHelperFactory.ExecuteScalar(
                connectionStringSplendidmyApp, 
                CommandType.StoredProcedure, 
                "GetCustomerNumber", 
                new SqlParameter("@id", id)
            );
        return obj.TrimString();
    }
    
    0 讨论(0)
提交回复
热议问题