Присвоить ноль для SqlParameter - PullRequest
162 голосов
/ 29 декабря 2010

Следующий код выдает ошибку - «Нет неявного преобразования из DBnull в 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;

Ответы [ 18 ]

298 голосов
/ 29 декабря 2010

Проблема в том, что оператор ?: не может определить тип возвращаемого значения, поскольку вы возвращаете либо значение int, либо значение типа DBNull, которые несовместимы.

Конечно, вы можете привестиэкземпляр AgeIndex будет иметь тип object, который будет удовлетворять требованию ?:.

Вы можете использовать оператор ?? слияния нуля следующим образом

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

Вот цитатаиз документации MSDN для оператора ?:, объясняющего проблему

Либо тип first_expression и second_expression должен совпадать, либо неявное преобразование должно существовать из одного типак другому.

87 голосов
/ 27 декабря 2013

Принятый ответ предлагает использовать приведение. Однако большинство типов SQL имеют специальное поле Null, которое можно использовать, чтобы избежать этого приведения.

Например, SqlInt32.Null "Представляет DBNull, который может быть назначен этому экземпляру класса SqlInt32."

int? example = null;
object exampleCast = (object) example ?? DBNull.Value;
object exampleNoCast = example ?? SqlInt32.Null;
24 голосов
/ 29 декабря 2010

Вам необходимо передать DBNull.Value как нулевой параметр в SQLCommand, если в хранимой процедуре не указано значение по умолчанию (если вы используете хранимую процедуру). Наилучший подход - назначить DBNull.Value для любого пропущенного параметра перед выполнением запроса, и следующий foreach сделает эту работу.

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

В противном случае измените эту строку:

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

следующим образом:

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

Поскольку вы не можете использовать разные типы значений в условном выражении, поскольку DBNull и int отличаются друг от друга. Надеюсь, это поможет.

17 голосов
/ 14 апреля 2017

С одной строкой кода попробуйте это:

var piParameter = new SqlParameter("@AgeIndex", AgeItem.AgeIndex ?? (object)DBNull.Value);
5 голосов
/ 29 декабря 2010

Попробуйте это:

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;
3 голосов
/ 12 сентября 2016

Если вы используете условный (троичный) оператор, компилятору требуется неявное преобразование между обоими типами, в противном случае вы получите исключение.

Так что вы можете исправить это, приведя один из обоих к System.Object:

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

Но так как результат не очень хорош, и вы всегда должны помнить этот кастинг, вы можете использоватьтакой метод расширения вместо:

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

Тогда вы можете использовать этот краткий код:

planIndexParameter.Value = AgeItem.AgeIndex.GetDBNullOrValue();
1 голос
/ 02 мая 2014

Рассмотрите возможность использования доступной структуры Nullable (T). Это позволит вам устанавливать значения только в том случае, если они у вас есть, и ваши объекты SQL Command будут распознавать обнуляемое значение и обрабатываться соответствующим образом без хлопот с вашей стороны.

1 голос
/ 29 декабря 2010

На мой взгляд, лучше сделать это с помощью свойства Параметры класса SqlCommand :

public static void AddCommandParameter(SqlCommand myCommand)
{
    myCommand.Parameters.AddWithValue(
        "@AgeIndex",
        (AgeItem.AgeIndex== null) ? DBNull.Value : AgeItem.AgeIndex);
}
0 голосов
/ 09 апреля 2017

Я использую простой метод с нулевой проверкой.

    public SqlParameter GetNullableParameter(string parameterName, object value)
    {
        if (value != null)
        {
            return new SqlParameter(parameterName, value);
        }
        else
        {
            return new SqlParameter(parameterName, DBNull.Value);
        }
    }
0 голосов
/ 27 марта 2017

Простой метод расширения для этого будет:

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