习惯性的,我写sqlParameter对象的时候,喜欢new SqlParameter("@pxx", 0),另外一种写法:var _pxx = new sqlParameter("@pxx", sqlDbType.Int); _pxx.value = 0; 但是今天遇到1个问题是,我在执行存储过程的时候,其中1个参数需要的是int类型的,而且业务上要求传0过去,那么我使用第一种方式创建对象,并cmd.parameters.add(p),这样的话通过sql profiler跟踪出来执行的是,@pxx = default;然后就报错了,然后同样的方式,我传1过去,执行存储过程就能正确得到1,并且查询过正确的结果,使用第2种方式的话,传0和1都没问题,可以得到正确的结果,所以我现在有疑问了,第1种方式创建对象,存在隐式转换,int类型的默认值又是0,如果我想给个0值,并不应该给我转换为default字样才对,查到了sqlCommand.Parameters.Add()函数,其中都是没有任何转换的(即排除这部分可能会存在问题),那么微软内部把我创建的sqlParameter对象添加到cmd的时候,又是怎样处理的?上述2种方式的区别又在哪里?如果微软帮我们做了一些垃圾的转换,我们如何知道哪些情况下会被转换出错(比如说今天遇到int类型被转换,那么string为空值会不会被转换,其他类型呢,有没有1个参考的address)?
高人就是高人, 一击就中要害。
@问天何必: 乱回答什么呀
通过第一种方式创建的sqlDbType为BigInt,但是要是值为1的话,就变成了sqlDbType.Int,为什么bigInt的类型的参数值会被转化为default呢
@Thirty: var _pxx = new SqlParameter("@pxx", 0);
_pxx.SqlValue ???
_pxx.Value ???
@Launcher: var _pxx = new SqlParameter("@pxx", 0);
Result:
_pxx.SqlDbType = BigInt
_pxx.SqlValue = 啥都没打印出来
_pxx.Value = 啥都没打印出来
@Launcher: 通过查看,跟踪.NET源代码,有如下代码测试:
public enum Fruit { Apple, Orange, Sex } public class Animal { public Fruit ff; public Animal() { Console.Write("this构造函数...."); } public Animal(Fruit _f) : this(){ Console.Write("Fruit ...."); this.ff = _f; } public Animal(object other) : this() { Console.Write("other ...."); } }
然后创建Animal对象:
public class Program { static void Main(string[] args) { //Amazing! Animal an = new Animal(0); // wil log: this构造函数....Fruit .... Animal an2 = new Animal(1); // wil log: this构造函数....other .... Console.ReadKey(); } }
神奇!
@Thirty: 其实你把鼠标悬停在 “SqlParameter("@pxx", 0);” 上,你就能看到实际调用的是哪个重载版本。这是一个编译时行为。
@Launcher: 看不到啊,不带参数的..你那边能看到吗?我的VS2013版本。
@Thirty: “这是一个编译时行为”,所以不是调试的时候看,而是在编辑源代码的状态下看。
@Launcher: Oh, 3Q, I see.
如果你真的想清楚这个问题,建议使用.net Reflector, 这类问题根本不需要问人的,自己分析代码就可以很快找到答案。
大概已经解决,你的回答启发了我,我以前一直以为.NET源代码没办法查看,谢谢