c# - validar - No se puede convertir el objeto del tipo ''System.DBNull'' para escribir ''System.String`
validar null en c# (10)
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?
Con una simple función genérica puede hacer que esto sea muy fácil. Solo haz esto:
return ConvertFromDBVal<string>(accountNumber);
usando la función:
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;
}
}
Convertirlo Me gusta
string s = System.DBNull.value.ToString();
Este es el método genérico que utilizo para convertir cualquier objeto que pueda ser DBNull.Value:
public static T ConvertDBNull<T>(object value, Func<object, T> 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);
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.
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.
Puede usar el operador coalescente nulo de C #
return accountNumber ?? string.Empty;
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()
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
Supongo que puedes hacerlo así:
string accountNumber = DBSqlHelperFactory.ExecuteScalar(...) as string;
Si accountNumber es nulo, significa que fue DBNull no string :)
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();
}