locked
主题修改成 发现一个ado.net使用雷区,当你用重载的parameters构造函数时,如果打算传入一个int类型的0值必须要使用Convert.Int32方法 RRS feed

  • 问题

  •  

    不知道咋的了,最近老是发现clr的问题,严重印象人品和感情。

     

    出现这个异常时感觉很诡异,代码如下:

     

    SqlParameter[] paramters = new SqlParameter[2];

    paramters[0] = new SqlParameter("@accountId", 25);

    paramters[1] = new SqlParameter("@lotsize", 0);

               try
               {
                   retObject = DBFacade.GetInstance().ExecuteScalar(sqlInsertString, paramters);
                   positionId = Convert.ToInt32(retObject);
               }
               catch (Exception e)
               {
                   return null;
               }

    运行这段代码开发平台会报出如下错误:

    “不能将值 NULL 插入列 'lot_size',表 'RMM.Enterprise.dbo.position';列不允许有空值。INSERT 失败。
    语句已终止。”

     

    这个lot_size在数据库中千真万确的是个整形int值,数据库要求其不能为null且没有设默认值,这我就必须插入一个0作为合理的初始化值,但会引发如上错误。我怀疑是编译器将int 0值当作了null地址,因为在系统中Null其实是悬空地址--0也就是0,而其new SqlParameter是他是要将int 形进行装箱操作,因此错误就出现在这里。因此我对代码作了如下改变以此证明推断

     

    1 将paramters[1] = new SqlParameter("@lotsize", 0); 改为 

          paramters[1] = new SqlParameter("@lotsize", 1);

    运行代码,没有引发异常,说明除0外其他值是可以通过装箱的

     

    2 增加 int[] value = new int[1]; // 一个整形的一维数组,其意义类似c++,由于是引用类型就可以避免装箱了

       value[0] = 0; //为其复制

       将paramters[1] = new SqlParameter("@lotsize", 0); 改为

      paramters[1] = new SqlParameter("@lotsize", value[0]);

    运行代码通过,没有引发异常

     

     

    结论我使用int[] 来代替int 就能正常通过,说明了什么?说明.net 运行时在处理这个地方的装箱是有问题的,它没能正确理解等于0的int值和悬空地址0 null之间区别。

     

     

    唉伤脑筋呀,半个上午就这样流失掉了。

     

     

    更正, 不是装箱问题是有重载函数在作怪

    2008年1月17日 4:05

答案

  •  

    下午查下msdn发现果然有使用警告,如下:

    Use caution when you use this overload of the SqlParameter constructor to specify integer parameter values. Because this overload takes a value of type Object, you must convert the integral value to an Object type when the value is zero, as the following C# example demonstrates.

    Parameter = new SqlParameter("@pname", Convert.ToInt32(0));
    这个不是clr的错误是因为这个重载方法在作怪:SqlParameter (string, SqlDbType)
    2008年1月17日 5:16