Tengo código siguiente para especificar los parámetros para la consulta SQL. Me estoy haciendo una excepción cuando yo uso Code 1; pero funciona bien cuando uso Code 2. En Code 2 tenemos un cheque por nulo y, por tanto, un if..else bloque.

Excepción:

La consulta parametrizada ‘(@application_ex_id nvarchar(4000))SELECCIONE E. application_ex_id Un’ espera que el parámetro ‘@application_ex_id’, que no fue suministrado.

Código 1:

command.Parameters.AddWithValue("@application_ex_id", logSearch.LogID);

Código 2:

if (logSearch.LogID != null)
{
         command.Parameters.AddWithValue("@application_ex_id", logSearch.LogID);
}
else
{
        command.Parameters.AddWithValue("@application_ex_id", DBNull.Value );
}

PREGUNTA

  1. ¿Puede por favor explicar por qué es incapaz de tomar NULO de logSearch.LogID valor en el Código 1 (pero capaz de aceptar DBNull)?

  2. Existe una mejor código para manejar esto?

Referencia:

  1. Asignar null a un SqlParameter
  2. El tipo de datos devuelto varía basado en los datos de la tabla
  3. Error de conversión de base de datos de tipo smallint en C# que aceptan valores null int
  4. ¿Cuál es el punto de DBNull?

CÓDIGO

    public Collection<Log> GetLogs(LogSearch logSearch)
{
Collection<Log> logs = new Collection<Log>();
using (SqlConnection connection = new SqlConnection(connectionString))
{
connection.Open();
string commandText = @"SELECT  *
FROM Application_Ex E 
WHERE  (E.application_ex_id = @application_ex_id OR @application_ex_id IS NULL)";
using (SqlCommand command = new SqlCommand(commandText, connection))
{
command.CommandType = System.Data.CommandType.Text;
//Parameter value setting
//command.Parameters.AddWithValue("@application_ex_id", logSearch.LogID);
if (logSearch.LogID != null)
{
command.Parameters.AddWithValue("@application_ex_id", logSearch.LogID);
}
else
{
command.Parameters.AddWithValue("@application_ex_id", DBNull.Value );
}
using (SqlDataReader reader = command.ExecuteReader())
{
if (reader.HasRows)
{
Collection<Object> entityList = new Collection<Object>();
entityList.Add(new Log());
ArrayList records = EntityDataMappingHelper.SelectRecords(entityList, reader);
for (int i = 0; i < records.Count; i++)
{
Log log = new Log();
Dictionary<string, object> currentRecord = (Dictionary<string, object>)records[i];
EntityDataMappingHelper.FillEntityFromRecord(log, currentRecord);
logs.Add(log);
}
}
//reader.Close();
}
}
}
return logs;
}
  • ¿Qué significa para ti el mejor? Código 2 es la forma correcta de enviar un valor nulo a una base de datos.
InformationsquelleAutor Lijo | 2012-11-19

4 Comentarios

  1. 122

    Molesto, no lo es.

    Puede utilizar:

    command.Parameters.AddWithValue("@application_ex_id",
    ((object)logSearch.LogID) ?? DBNull.Value);

    O, alternativamente, utilizar una herramienta como «dapper», que va a hacer todo lo que se pelee por usted.

    Por ejemplo:

    var data = conn.Query<SomeType>(commandText,
    new { application_ex_id = logSearch.LogID }).ToList();

    Estoy tentado para agregar un método a dapper para obtener el IDataReader… no sé todavía si es una buena idea.

    • en efecto; la mayoría de las cosas se puede… pero no me gusta la adición de métodos de extensión en object, y no sabemos si eso es Nullable<T> vs string, etc… pero sí: se puede hacer con bastante facilidad.
    • Yo estaba pensando en una extensión en el Parameters de la propiedad – es que un Object?
    • hmmm, sí lo es, y veo lo que quieres decir… tal vez AddWithValueAndTreatNullTheRightDamnedWay(...)
    • ¿Puede por favor explicar por qué es incapaz de tomar NULO de logSearch.LogID valor en el Código 1 (pero capaz de aceptar DBNull)?
    • porque null en el valor de un parámetro significa «no enviar este parámetro». Yo sospecho que fue una mala decisión que simplemente se cuece en. De hecho, creo que más de DBNull fue, fundamentalmente, una mala decisión que se metió al horno en: stackoverflow.com/a/9632050/23354
  2. 42

    Me resulta más fácil escribir un método de extensión para el SqlParameterCollection que controla los valores null:

    public static SqlParameter AddWithNullableValue(
    this SqlParameterCollection collection,
    string parameterName,
    object value)
    {
    if(value == null)
    return collection.AddWithValue(parameterName, DBNull.Value);
    else
    return collection.AddWithValue(parameterName, value);
    }

    A continuación, usted sólo tiene que llamar como:

    sqlCommand.Parameters.AddWithNullableValue(key, value);
    • valor puede ser int o int? string, bool o bool?, DateTime Datetime o?, etc ?
    • Sí…
    • He leído Marc respuesta y pensé «creo que preferiría sólo tienes que escribir un método de extensión para la colección de Parámetros», entonces me desplaza hacia abajo un pelo… (cosa buena acerca de un método de extensión es que puedo hacer un solo buscar/reemplazar y después de todas mis actualizaciones del código terminado)
    • Esto debe ser aceptado respuesta.
    • Gran solución…los métodos de Extensión debe ser definido en una clase estática. Cómo: Implementar y Llamar a un Método de Extensión Personalizado
    • Tal vez me equivoco (como una especie de C# novato), pero no podía hacerlo de forma más concisa como este: return collection.AddWithValue(parameterName, value ?? DBNull.Value);
    • Sí, usted puede hacer eso también. Es sólo una cuestión de gusto.

  3. 2

    Sólo en caso de que usted está haciendo esto, mientras que llamar a un procedimiento almacenado: creo que es más fácil de leer, si se declara un valor por defecto del parámetro y agregar sólo cuando sea necesario.

    Por ejemplo:
    (sql)

    DECLARE PROCEDURE myprocedure
    @myparameter [int] = NULL
    AS BEGIN

    (c#)

    int? myvalue = initMyValue();
    if (myvalue.hasValue) cmd.Parameters.AddWithValue("myparamater", myvalue);

    Sé que esto es viejo, pero me parece que este útil y quería compartir.

  4. 1

    algún problema, permitió Necesariamente establecer SQLDbType

    command.Parameters.Add("@Name", SqlDbType.NVarChar);
    command.Parameters.Value=DBNull.Value

    donde SqlDbType.NVarChar de escribir. Necesariamente conjunto de tipo SQL.
    Disfrutar

Dejar respuesta

Please enter your comment!
Please enter your name here