将null分配给SqlParameter

Rel*_*ity 177 c# dbnull sqlparameter

以下代码给出了一个错误 - "没有从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;
Run Code Online (Sandbox Code Playgroud)

Chr*_*lor 315

问题是?:操作员无法确定返回类型,因为要么返回int值不兼容的值或DBNull类型值.

您当然可以将AgeIndex的实例转换为object满足?:要求的类型.

您可以使用??null-coalescing运算符,如下所示

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

下面是从报价MSDN文档?:操作,说明问题

first_expression和second_expression的类型必须相同,或者从一种类型到另一种类型必须存在隐式转换.

  • 从技术上讲,使用null-coalescing运算符`??`的解决方案与使用常规三元`?:`的解决方案是一样的 - 你仍然需要将`AgeItem.AgeIndex`强制转换为一个对象:`planIndexParameter.Value = AgeItem.AgeIndex.HasValue?(object)AgeItem.AgeIndex:DBNull.Value;`. (3认同)

Bri*_*ian 93

接受的答案建议使用演员阵容.但是,大多数SQL类型都有一个特殊的Null字段,可用于避免此强制转换.

例如,SqlInt32.Null"表示可以分配给此SqlInt32类实例的DBNull".

int? example = null;
object exampleCast = (object) example ?? DBNull.Value;
object exampleNoCast = example ?? SqlInt32.Null;
Run Code Online (Sandbox Code Playgroud)

  • @JasDev:我依旧回忆起在对高级用户(我认为是Marc Gravell)的评论中描述这个技巧并被告知它只适用于Microsoft SQL Server. (6认同)
  • 该建议看起来很有希望所以我尝试了"System.Data.SqlTypes.SqlString.Null"但它不起作用.它将实际字符串"Null"("N","u","l","l")放入字段中,而将其留空并使用true(null).然而,旧的2010"接受的答案"使用演员与(对象)?DBNull.Value正常工作.(我使用的ADO.NET提供程序是SQLite,但我不确定这是否有所不同.)我建议其他人仔细测试Brian的提示,以确保null行为按预期工作. (2认同)

Sha*_*zim 28

除非在存储过程中指定了默认值(如果使用存储过程),否则需要在SQLCommand中将DBNull.Value作为空参数传递.最好的方法是在查询执行之前为任何缺少的参数分配DBNull.Value,并且在foreach之后将执行该任务.

foreach (SqlParameter parameter in sqlCmd.Parameters)
{
    if (parameter.Value == null)
    {
        parameter.Value = DBNull.Value;
    }
}
Run Code Online (Sandbox Code Playgroud)

否则改变这一行:

planIndexParameter.Value = (AgeItem.AgeIndex== null) ? DBNull.Value : AgeItem.AgeIndex;
Run Code Online (Sandbox Code Playgroud)

如下:

if (AgeItem.AgeIndex== null)
    planIndexParameter.Value = DBNull.Value;
else
    planIndexParameter.Value = AgeItem.AgeIndex;
Run Code Online (Sandbox Code Playgroud)

因为在条件语句中不能使用不同类型的值,因为DBNull和int彼此不同.希望这会有所帮助.


Adr*_*ian 19

使用一行代码,试试这个:

var piParameter = new SqlParameter("@AgeIndex", AgeItem.AgeIndex ?? (object)DBNull.Value);
Run Code Online (Sandbox Code Playgroud)


dec*_*one 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;
Run Code Online (Sandbox Code Playgroud)


Tim*_*ter 5

如果使用条件(三元)运算符,则编译器需要在这两种类型之间进行隐式转换,否则会出现异常。

因此,您可以通过将以下两者之一转换为System.Object

planIndexParameter.Value = (AgeItem.AgeIndex== null) ? DBNull.Value : (object) AgeItem.AgeIndex;
Run Code Online (Sandbox Code Playgroud)

但是由于结果不是很漂亮,并且您始终必须记住这种转换,因此可以改用以下扩展方法:

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;
}
Run Code Online (Sandbox Code Playgroud)

然后,您可以使用以下简洁代码:

planIndexParameter.Value = AgeItem.AgeIndex.GetDBNullOrValue();
Run Code Online (Sandbox Code Playgroud)