107 votes

Exception lorsque le paramètre AddWithValue est NULL

J'ai le code suivant pour spécifier les paramètres d'une requête SQL. J'obtiens l'exception suivante lorsque j'utilise Code 1 ; mais cela fonctionne bien lorsque j'utilise Code 2 . Sur Code 2 nous avons une vérification de la nullité 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 expliquer pourquoi il est impossible de prendre NULL de la valeur logSearch.LogID dans le code 1 (mais capable d'accepter DBNull) ?

  2. Existe-t-il un meilleur code pour gérer cela ?

Référence :

  1. Assigner null à un SqlParameter
  2. Le type de données renvoyé varie en fonction des données de la table.
  3. Erreur de conversion d'un smallint de base de données en int nullable C#
  4. Quel est l'intérêt 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;
    }

177voto

Marc Gravell Points 482669

C'est ennuyeux, n'est-ce pas ?

Vous pouvez utiliser :

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

Vous pouvez également utiliser un outil tel que "dapper", qui se chargera de tout ce travail pour vous.

Par exemple :

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

Je suis tenté pour ajouter une méthode à dapper afin d'obtenir la IDataReader ... pas encore vraiment sûr que ce soit une bonne idée.

65voto

Yasmani Llanes Points 2280

Je trouve qu'il est plus facile d'écrire une méthode d'extension pour la fonction 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);
}

Alors tu l'appelles juste comme ça :

sqlCommand.Parameters.AddWithNullableValue(key, value);

5voto

z00l Points 315

Au cas où vous feriez cela en appelant une procédure stockée : Je pense que c'est plus facile à lire si vous déclarez une valeur par défaut sur le paramètre et que vous ne l'ajoutez que lorsque c'est nécessaire.

SQL :

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

C# :

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

0voto

user1599225 Points 11

Un problème, autorisé avec Necessarily set SQLDbType

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

où SqlDbType.NVarChar est votre type. Définit nécessairement le type SQL.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X