No se puede convertir el objeto del tipo ‘System.DBNull’ para escribir ‘System.String`

Recibí el error anterior en mi aplicación. Aquí está el código original

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

Reemplacé con

 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(); } } 

¿Hay una mejor manera de evitar esto?

Se puede usar una forma más corta:

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

EDITAR: No han prestado atención a ExecuteScalar. Realmente devuelve nulo si el campo está ausente en el resultado de la devolución. Entonces, use en su lugar:

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

Con una simple función genérica puede hacer que esto sea muy fácil. Solo haz esto:

 return ConvertFromDBVal(accountNumber); 

usando la función:

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

ExecuteScalar regresará

  • nulo si no hay un conjunto de resultados
  • de lo contrario, la primera columna de la primera fila del conjunto de resultados, que puede ser DBNull.

Si sabe que la primera columna del conjunto de resultados es una cadena, entonces para cubrir todas las bases necesita verificar tanto null como DBNull. Algo como:

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

El código anterior se basa en el hecho de que DBNull.ToString devuelve una cadena vacía.

Si accountNumber fuera de otro tipo (digamos entero), entonces necesitarías ser más explícito:

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

Si está seguro de que su conjunto de resultados siempre tendrá al menos una fila (por ejemplo, SELECT COUNT (*) …), puede omitir la comprobación de nulo.

En su caso, el mensaje de error “No se puede convertir el objeto de tipo ‘System.DBNull’ para escribir ‘System.String`” indica que la primera columna de su conjunto de resultados es un valor DBNUll. Esto es del elenco a la cadena en la primera línea:

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

El comentario de Marc_s de que no necesita verificar DBNull.Value es incorrecto.

Puede usar el operador coalescente nulo de C #

 return accountNumber ?? string.Empty; 

Hay otra forma de solucionar este problema. ¿Qué hay de modificar el procedimiento de su tienda? mediante el uso de la función sql de ISNULL (su campo, “”), puede devolver una cadena vacía si el valor de retorno es nulo.

Entonces tienes tu código limpio como versión original.

Este es el método genérico que utilizo para convertir cualquier objeto que pueda ser DBNull.Value:

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

uso:

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

corta:

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

Supongo que puedes hacerlo así:

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

Si accountNumber es nulo, significa que fue DBNull no string 🙂

String.Concat transforma DBNull y valores nulos en una cadena vacía.

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

Sin embargo, creo que pierdes algo sobre la comprensibilidad del código

Como obtuve una instancia que no es nula y si comparé con DBNULL obtuve Operator '==' cannot be applied to operands of type 'string' and 'system.dbnull' excepción, y si traté de cambiar para comparar a NULL, simplemente no funcionó (dado que DBNull es un objeto) incluso esa es la respuesta aceptada.

Decidí simplemente usar la palabra clave ‘es’. Entonces el resultado es muy legible:

data = (item is DBNull) ? String.Empty : item

Utilizo una extensión para eliminar este problema para mí, que puede o no ser lo que buscas.

Dice así:

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

Nota:

¡Esta extensión no devuelve valores null ! Si el elemento es null o DBNull.Value , devolverá una cadena vacía.

Uso:

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

Convertirlo Me gusta

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