Excepción cuando el parámetro AddWithValue es NULL

Tengo el siguiente código para especificar parámetros para la consulta SQL. Estoy siguiendo la excepción cuando uso el Code 1 ; pero funciona bien cuando uso el Code 2 . En el Code 2 tenemos un cheque para nulo y, por lo tanto, un bloque if..else .

Excepción:

La consulta parametrizada ‘(@application_ex_id nvarchar (4000)) SELECT E.application_ex_id A’ espera el parámetro ‘@application_ex_id’, que no se proporcionó.

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 explicar por qué no puede tomar NULL del valor logSearch.LogID en el Código 1 (pero puede aceptar DBNull)?

  2. ¿Hay un código mejor para manejar esto?

Referencia :

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

CÓDIGO

  public Collection GetLogs(LogSearch logSearch) { Collection logs = new Collection(); 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 entityList = new Collection(); entityList.Add(new Log()); ArrayList records = EntityDataMappingHelper.SelectRecords(entityList, reader); for (int i = 0; i < records.Count; i++) { Log log = new Log(); Dictionary currentRecord = (Dictionary)records[i]; EntityDataMappingHelper.FillEntityFromRecord(log, currentRecord); logs.Add(log); } } //reader.Close(); } } } return logs; } 

Molesto, ¿verdad?

Puedes usar:

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

O, como alternativa, utilice una herramienta como “dapper”, que hará todo lo que le moleste.

Por ejemplo:

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

Estoy tentado de agregar un método para apresurarme para obtener el IDataReaderIDataReader no estoy seguro de si es una buena idea.

Me resulta más fácil simplemente escribir un método de extensión para SqlParameterCollection que maneja valores nulos:

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

Entonces simplemente lo llamas así:

 sqlCommand.Parameters.AddWithNullableValue(key, value); 

En caso de que esté haciendo esto al llamar a un procedimiento almacenado: creo que es más fácil de leer si declara un valor predeterminado en el parámetro y lo agrega solo cuando es necesario.

Por ejemplo: (sql)

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

(do#)

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

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

algún problema, permitido con Set SQLDbType Necesariamente

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

donde escribe SqlDbType.NVarChar. Necesariamente establece el tipo de SQL. Enjou

Crea una clase estática como esta:

 public static class Extensions { public static string RemoveNulls(this string container) { if (container == null) container = ""; return container; } } 

Luego en tu código, haz esto:

 Parameters.AddWithValue(sName, Value.RemoveNulls()); 

Esto es a prueba de balas y muy fácil de usar