2010-12-29 3 views
129

В следующем коде приведена ошибка - «Нет неявного преобразования из DBnull в int».Присвоить значение null SqlParameter

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

Вы должны бросить AgeItem.AgeIndex возразить я думаю ... http://stackoverflow.com/questions/202271/why- is-this-code-invalid-in-c (btw, почему '==' в конце 3-й строки?) – Greg

ответ

251

Проблема заключается в том, что оператор ?: не может определить тип возврата, потому что вы либо возвращаете значение 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 documentation для ?: оператора, который объясняет проблему

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

+0

Почему не возникает ли исключение при попытке передать значение null объекту? Я бы подумал, что это должно быть «AgeItem.AgeIndex как объект» –

+0

@Niels Brinch, не было бы исключения, потому что null - это объект и до тех пор, пока вы не пытаетесь разыменовать его, это совершенно законно. Тем не менее, в этом примере для объекта не выбрано значение null, это DBNull.Value, который фактически является типом значения. The ?? оператор говорит «если AgetItem.AgeIndex имеет значение null, тогда возвращает DBNull.Value иначе returen AgeItem.AgeIndex», тогда ответ будет передан объекту. Для получения дополнительной информации см. Оператор null coalescing. http://msdn.microsoft.com/en-us/library/ms173224.aspx –

+3

Технически ваше решение, использующее оператор с нулевым коалесцированием '??', является тем же самым решением, как если бы вы использовали обычный тернарный '?: '- вам все равно нужно нарисовать' AgeItem.AgeIndex' для объекта: 'planIndexParameter.Value = AgeItem.AgeIndex.HasValue? (объект) AgeItem.AgeIndex: DBNull.Value; '. – newfurniturey

0

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

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

Другими словами, если параметр является недействительным просто не отправить его в хранимая процедура (при условии, конечно, что хранимая процедура принимает нулевые параметры, подразумевается в вашем вопросе).

+0

Но теперь вы просто упускаете параметр - я очень сомневаюсь, что хранимая процедура будет счастлива об этом .... скорее всего, вызов не будет утверждать, что «нет значения для параметра @AgeIndex, который ожидался» ..... –

+0

Wow. Суровая. Просто напишите сохраненный proc по умолчанию на значение, если параметр не передан (@AgeIndex int = 0). Бывает все время. Клиент может либо принять значение по умолчанию, либо переопределить его, передав параметр. Почему нисходящий? – Flipster

1

На мой взгляд, лучший способ это сделать это с Parameters свойством SqlCommand класса:

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

Но если значение 'DBNull.Value', ADO.NET может немного затрудниться с тем, что SqlDbType может быть ........ это удобно - но немного опасно .... –

18

Вам нужно пройти 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 и междунар отличаются от друг друга. Надеюсь, это поможет.

5

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

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

попробовать что-то вроде этого:

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

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

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

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

Предложение выглядело многообещающим, поэтому я попробовал «System.Data.SqlTypes.SqlString.Null», но он не работает. Он помещает фактическую строку «Null» («N», «u», «l», «l») в поле, вместо этого оставляя ее пустой с true (null). Тем не менее, старый принятый ответ 2010 года, в котором используется листинг с (объектом)? DBNull.Value работает правильно. (Поставщик ADO.NET, который я использовал, был SQLite, но я не уверен, что это имеет значение.) Я предлагаю, чтобы другие тщательно тестировали совет Брайана, чтобы убедиться, что поведение NULL работает должным образом. – JasDev

+4

@JasDev: Я смутно вспоминаю описание этого трюка в комментарии к высокопоставленному пользователю (я думаю, Марк Гравелл), и ему говорят, что он работает только на Microsoft SQL Server. – Brian

+0

@JasDev провайдер будет той разницей, что это работает в SQL Server как точка Brain. – Lankymart

0
int? nullableValue = null; 
object nullableValueDB 
{ 
    get{ 
     if(nullableValue==null) 
      return DBNull.Value; 
     else 
      return (int)nullableValue; 
    } 
} 

Я решения, как это.

0
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
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); 
1

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

0

Это то, что я просто делаю ...

 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
  dynamic psd = DBNull.Value; 

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


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

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

Так что вы можете это исправить путем литья один из обоих к 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(); 
0

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

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

Что-нибудь случилось с просто создать «обнуляемым» параметр делать?

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

С одной строки кода, попробуйте следующее:

var piParameter = new SqlParameter("@AgeIndex", AgeItem.AgeIndex ?? (object)DBNull.Value); 
Смежные вопросы