web-dev-qa-db-fra.com

Assigne null à un SqlParameter

Le code suivant donne une erreur - "Aucune conversion implicite de DBnull en int."

SqlParameter[] parameters = new SqlParameter[1];    
SqlParameter planIndexParameter = new SqlParameter("@AgeIndex", SqlDbType.Int);
planIndexParameter.Value = (AgeItem.AgeIndex== null) ? DBNull.Value : AgeItem.AgeIndex;
parameters[0] = planIndexParameter;
151
Relativity

Le problème est que l'opérateur ?: ne peut pas déterminer le type de retour car vous renvoyez une valeur int ou une valeur de type DBNull, qui ne sont pas compatibles.

Vous pouvez bien sûr convertir l'instance de AgeIndex en type object, ce qui satisferait l'exigence ?:.

Vous pouvez utiliser l'opérateur ?? null-coalescing comme suit

SqlParameter[] parameters = new SqlParameter[1];     
SqlParameter planIndexParameter = new SqlParameter("@AgeIndex", SqlDbType.Int);
planIndexParameter.Value = (object)AgeItem.AgeIndex ?? DBNull.Value;
parameters[0] = planIndexParameter; 

Voici une citation de la documentation MSDN pour l'opérateur ?: qui explique le problème

Soit les types first_expression et second_expression doivent être identiques, soit une conversion implicite doit exister d'un type à l'autre.

286
Chris Taylor

La réponse acceptée suggère d'utiliser un casting. Cependant, la plupart des types SQL ont un champ Null spécial qui peut être utilisé pour éviter cette conversion. 

Par exemple, SqlInt32.Null "Représente un DBNull pouvant être affecté à cette instance de la classe SqlInt32."

int? example = null;
object exampleCast = (object) example ?? DBNull.Value;
object exampleNoCast = example ?? SqlInt32.Null;
81
Brian

Vous devez transmettre DBNull.Value en tant que paramètre null dans SQLCommand, sauf si une valeur par défaut est spécifiée dans la procédure stockée (si vous utilisez une procédure stockée). La meilleure approche consiste à affecter DBNull.Value à tout paramètre manquant avant l'exécution de la requête. Le suivi de foreach fera le travail.

foreach (SqlParameter parameter in sqlCmd.Parameters)
{
    if (parameter.Value == null)
    {
        parameter.Value = DBNull.Value;
    }
}

Sinon changez cette ligne:

planIndexParameter.Value = (AgeItem.AgeIndex== null) ? DBNull.Value : AgeItem.AgeIndex;

Comme suit:

if (AgeItem.AgeIndex== null)
    planIndexParameter.Value = DBNull.Value;
else
    planIndexParameter.Value = AgeItem.AgeIndex;

Parce que vous ne pouvez pas utiliser différents types de valeurs dans une instruction conditionnelle, car DBNull et int sont différents. J'espère que cela aidera.

21
ShahidAzim

Avec une ligne de code, essayez ceci:

var piParameter = new SqlParameter("@AgeIndex", AgeItem.AgeIndex ?? (object)DBNull.Value);
11
Adrian

Essaye ça:

SqlParameter[] parameters = new SqlParameter[1];    
SqlParameter planIndexParameter = new SqlParameter("@AgeIndex", SqlDbType.Int);

planIndexParameter.IsNullable = true; // Add this line

planIndexParameter.Value = (AgeItem.AgeIndex== null) ? DBNull.Value : AgeItem.AgeIndex== ;
parameters[0] = planIndexParameter;
5
decyclone

Si vous utilisez l'opérateur conditionnel (ternaire), le compilateur a besoin d'une conversion implicite entre les deux types, sinon vous obtenez une exception. 

Vous pouvez donc résoudre ce problème en lançant l’un des deux en System.Object:

planIndexParameter.Value = (AgeItem.AgeIndex== null) ? DBNull.Value : (object) AgeItem.AgeIndex;

Mais comme le résultat n’est pas vraiment joli et que vous devez toujours vous rappeler ce casting, vous pouvez utiliser une telle méthode d’extension:

public static object GetDBNullOrValue<T>(this T val)
{
    bool isDbNull = true;
    Type t = typeof(T);

    if (Nullable.GetUnderlyingType(t) != null)
        isDbNull = EqualityComparer<T>.Default.Equals(default(T), val);
    else if (t.IsValueType)
        isDbNull = false;
    else
        isDbNull = val == null;

    return isDbNull ? DBNull.Value : (object) val;
}

Ensuite, vous pouvez utiliser ce code concis:

planIndexParameter.Value = AgeItem.AgeIndex.GetDBNullOrValue();
2
Rango

À mon avis, la meilleure solution consiste à utiliser la propriété Parameters de la SqlCommand class

public static void AddCommandParameter(SqlCommand myCommand)
{
    myCommand.Parameters.AddWithValue(
        "@AgeIndex",
        (AgeItem.AgeIndex== null) ? DBNull.Value : AgeItem.AgeIndex);
}
1
user432219

Pensez à utiliser la structure Nullable (T) disponible. Cela vous permettra de définir des valeurs uniquement si vous les avez, et vos objets de commande SQL reconnaîtront la valeur nullable et le traiteront en conséquence, sans tracas de votre part.

1
Kanwar Singh
if (AgeItem.AgeIndex== null)  
    cmd.Parameters.Add(new SqlParameter("ParaMeterName", SqlDbType.DateTime).Value = DBNull);  
else  
    cmd.Parameters.Add(new SqlParameter("ParaMeterName", SqlDbType.DateTime).Value = AgeItem.AgeIndex);
0
Anil Kumar
            dynamic psd = DBNull.Value;

            if (schedule.pushScheduleDate > DateTime.MinValue)
            {
                psd = schedule.pushScheduleDate;
            }


            sql.DBController.RunGeneralStoredProcedureNonQuery("SchedulePush",
                     new string[] { "@PushScheduleDate"},
                     new object[] { psd }, 10, "PushCenter");
0
papapa

Une méthode d'extension simple pour cela serait:

    public static void AddParameter(this SqlCommand sqlCommand, string parameterName, 
        SqlDbType sqlDbType, object item)
    {
        sqlCommand.Parameters.Add(parameterName, sqlDbType).Value = item ?? DBNull.Value;
    }
0
Mark

Essaye ça:

if (AgeItem.AgeIndex != null)
{
   SqlParameter[] parameters = new SqlParameter[1];
   SqlParameter planIndexParameter = new SqlParameter("@AgeIndex", SqlDbType.Int);
   planIndexParameter.Value = AgeItem.AgeIndex;
   parameters[0] = planIndexParameter;
}

En d'autres termes, si le paramètre est null, n'envoyez pas simplement à votre proc stocké (en supposant bien sûr que le proc stocké accepte les paramètres nuls, ce qui est implicite dans votre question).

0
Flipster
if (_id_categoria_padre > 0)
{
    objComando.Parameters.Add("id_categoria_padre", SqlDbType.Int).Value = _id_categoria_padre;
}
else
{
    objComando.Parameters.Add("id_categoria_padre", DBNull.Value).Value = DBNull.Value;
}
0
Anil Kumar

J'utilise une méthode simple avec un contrôle nul.

    public SqlParameter GetNullableParameter(string parameterName, object value)
    {
        if (value != null)
        {
            return new SqlParameter(parameterName, value);
        }
        else
        {
            return new SqlParameter(parameterName, DBNull.Value);
        }
    }
0
Zhi An

essayez quelque chose comme ça:

if (_id_categoria_padre > 0)
{
    objComando.Parameters.Add("id_categoria_padre", SqlDbType.Int).Value = _id_categoria_padre;
}
else
{
    objComando.Parameters.Add("id_categoria_padre", DBNull.Value).Value = DBNull.Value;
}
0
user2574441

Mon code, travaillant dans un projet réel Regardez l'opérateur ternaire avant de faire le sqlparameter C'est la meilleure façon pour moi, avec vos problèmes:

    public bool Key_AddExisting
    (
          string clave
        , int? idHito_FileServer
        , int? idTipoDocumental_Almacen
        , string tipoExp_CHJ
        , int idTipoExp_Verti2
        , int idMov_Verti2
    )
    {
        List<SqlParameter> pars = new List<SqlParameter>()
        {
              new SqlParameter { ParameterName = "@Clave", Value = clave }
    LOOK -> , idHito_FileServer == null ? new SqlParameter { ParameterName = "@IdHito_FileServer", Value = DBNull.Value } : new SqlParameter { ParameterName = "@IdHito_FileServer", Value = idHito_FileServer }
    LOOK -> , idTipoDocumental_Almacen == null ? new SqlParameter { ParameterName = "@IdTipoDocumental_Almacen", Value = DBNull.Value } : new SqlParameter { ParameterName = "@IdTipoDocumental_Almacen", Value = idTipoDocumental_Almacen }
            , new SqlParameter { ParameterName = "@TipoExp_CHJ", Value = tipoExp_CHJ }
            , new SqlParameter { ParameterName = "@IdTipoExp_Verti2", Value = idTipoExp_Verti2 }
            , new SqlParameter { ParameterName = "@IdMov_Verti2", Value = idMov_Verti2 }
        };

        string sql = "INSERT INTO [dbo].[Enlaces_ClavesCHJ_MovimientosVerti2] " +
            "( " +
            "  [Clave] " +
            ", [IdHito_FileServer] " +
            ", [IdTipoDocumental_Almacen] " +
            ", [TipoExp_CHJ] " +
            ", [IdTipoExp_Verti2] " +
            ", [IdMov_Verti2] " +
            ") " +
            "VALUES" +
            "( " +
            "  @Clave" +
            ", @IdHito_FileServer" +
            ", @IdTipoDocumental_Almacen" +
            ", @TipoExp_CHJ" +
            ", @IdTipoExp_Verti2" +
            ", @IdMov_Verti2" +
            ")";

        return DbBasic.ExecNonQuery(ref this.conn, sql, pars);
    }
0
Ángel Ibáñez
int? nullableValue = null;
object nullableValueDB
{
   get{
       if(nullableValue==null)
          return DBNull.Value;
       else
          return (int)nullableValue;
   }
}

Je résous comme ça.

0
A Sinan Direk

C'est ce que je fais tout simplement ...

        var PhoneParam = new SqlParameter("@Phone", DBNull.Value);
        if (user.User_Info_Phone != null)
        {
            PhoneParam.SqlValue = user.User_Info_Phone;
        }

        return this.Database.SqlQuery<CustLogonDM>("UpdateUserInfo @UserName, @NameLast, @NameMiddle, @NameFirst, @Address, @City, @State, @PostalCode, @Phone",
            UserNameParam, NameLastParam, NameMiddleParam, NameFirstParam, AddressParam, CityParam, StateParam, PostalParam, PhoneParam).Single();
0
Tom Mack