web-dev-qa-db-fra.com

Exception lorsque le paramètre AddWithValue est NULL

J'ai le code suivant pour spécifier les paramètres pour la requête SQL. Je reçois l'exception suivante lorsque j'utilise Code 1; mais fonctionne bien quand j’utilise Code 2. Dans Code 2 nous avons un contrôle pour null et donc un if..else bloc.

Exception:

La requête paramétrée '(@application_ex_id nvarchar (4000)) SELECT E.application_ex_id A' attend le paramètre '@application_ex_id', qui n'a pas été fourni.

Code 1 :

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

Code 2 :

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

[~ # ~] question [~ # ~]

  1. Pouvez-vous s'il vous plaît expliquer pourquoi il est impossible de prendre NULL à partir de la valeur logSearch.LogID dans le code 1 (mais capable d'accepter DBNull)?

  2. Y at-il un meilleur code pour gérer cela?

Référence :

  1. Assigne null à un SqlParameter
  2. Le type de données retourné varie en fonction des données du tablea
  3. Erreur de conversion de la base de données smallint en C # nullable int
  4. Quel est le point de DBNull?

CODE

    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;
    }
73
Lijo

Ennuyant, n'est ce pas.

Vous pouvez utiliser:

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

Ou encore, utilisez un outil comme "dapper", qui fera tout ce bazar pour vous.

Par exemple:

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

Je suis tenté d'ajouter une méthode à dapper pour obtenir le IDataReader... je ne sais pas encore si c'est une bonne idée.

123
Marc Gravell

Je trouve plus facile d'écrire une méthode d'extension pour le SqlParameterCollection qui gère les valeurs nulles:

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

Ensuite, vous appelez juste comme:

sqlCommand.Parameters.AddWithNullableValue(key, value);
42
AxiomaticNexus

Juste au cas où vous le feriez en appelant une procédure stockée: je pense qu’il est plus facile de lire si vous déclarez une valeur par défaut sur le paramètre et ne l’ajoutez que lorsque cela est nécessaire.

Par exemple: (sql)

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

(c #)

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

Je sais que c'est vieux, mais je trouve cela utile et je voulais le partager.

2
z00l

un problème, autorisé avec Définir nécessairement SQLDbType

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

où vous tapez SqlDbType.NVarChar. Définit nécessairement le type SQL. Enjou

1
user1599225