Parameters.Add(string, object) 和 Parameters.AddWithValue 之间的区别

Posted

技术标签:

【中文标题】Parameters.Add(string, object) 和 Parameters.AddWithValue 之间的区别【英文标题】:Difference between Parameters.Add(string, object) and Parameters.AddWithValue 【发布时间】:2012-04-17 11:45:38 【问题描述】:

我阅读了 MSDN 文档和示例 here,我知道 Paramters.Add 调用的正确语法是:

   command.Parameters.Add("@ID", SqlDbType.Int);
   command.Parameters["@ID"].Value = customerID; 

您必须指定参数名称、SqlDbType 和带有.Value 的值。

现在,Parameters.AddWithValue 调用的正确语法是:

   command.Parameters.AddWithValue("@demographics", demoXml);

单行并跳过Type 部分。

我的问题是:当我这样做时,是怎么回事,

   command.Parameters.Add("@demographics", demoXml);
   // .Add method with .AddWithValue syntax

我没有收到任何编译错误,甚至更奇怪的是,执行代码时似乎一切正常?

【问题讨论】:

【参考方案1】:

在功能方面没有区别。事实上,两者都是这样做的:

return this.Add(new SqlParameter(parameterName, value));

他们弃用旧参数以支持 AddWithValue 的原因是为了增加额外的清晰度,以及因为第二个参数是 object,这使得某些人无法立即看出 Add 的重载是被调用,它们导致了截然不同的行为。

看看这个例子:

 SqlCommand command = new SqlCommand();
 command.Parameters.Add("@name", 0);

乍一看,它似乎在调用Add(string name, object value) 重载,但不是。它正在调用Add(string name, SqlDbType type) 过载!这是因为 0 可以隐式转换为枚举类型。所以这两行:

 command.Parameters.Add("@name", 0);

 command.Parameters.Add("@name", 1);

实际上导致调用了两种不同的方法。 1 不能隐式转换为枚举,因此它选择 object 重载。使用0,它选择枚举重载。

【讨论】:

唯一的事情是你必须忍受你以这种方式添加的每个参数的新警告。 是的,警告是因为 此重载已过时,如文档中所标记。同样来自文档,“在使用 SqlParameterCollection.Add 方法的此重载来指定整数参数值时要小心。” 如果像我一样好奇的人想知道为什么零可以隐式转换为枚举而不是任何其他整数。这是一个 SO 解释的链接,***.com/questions/14950750/… 也许我们应该将这个众所周知的答案与有关 AddWithValue 陷阱的更多信息结合起来。 blogs.msmvps.com/jcoehoorn/blog/2014/05/12/… 和 docs.microsoft.com/en-us/archive/msdn-magazine/2009/brownfield/…【参考方案2】:

不同之处在于使用 AddWithValue 时的隐式转换。如果您知道您正在执行的 SQL 查询(存储过程)正在接受 int、nvarchar 等类型的值,则没有理由在您的代码中重新声明它。

对于复杂类型场景(例如 DateTime、float),我可能会使用 Add,因为它更明确,但 AddWithValue 用于更直接的类型场景(Int 到 Int)。

【讨论】:

【参考方案3】:

如果不显式提供command.Parameters.Add("@ID", SqlDbType.Int); 中的类型,它将尝试将输入隐式转换为它所期望的。

这样做的缺点是隐式转换可能不是最佳的转换,并且可能会导致性能下降。

这里有一个关于这个主题的讨论: http://forums.asp.net/t/1200255.aspx/1

【讨论】:

【参考方案4】:

当我们使用CommandObj.Parameter.Add()时,它有2个参数,第一个是过程参数,第二个是它的数据类型,而.AddWithValue()有2个参数,第一个是过程参数,第二个是数据变量

CommandObj.Parameter.Add("@ID",SqlDbType.Int).Value=textBox1.Text;

.AddWithValue

CommandObj.Parameter.AddWitheValue("@ID",textBox1.Text);

其中ID是数据类型为Int的存储过程的参数

【讨论】:

【参考方案5】:

在功能方面没有区别

addwithvalue 方法将对象作为值。没有类型数据类型检查。如果数据类型与 SQL 表不匹配,这可能会导致错误。 add 方法要求您首先指定数据库类型。这有助于减少此类错误。

更多详情Please click here

【讨论】:

类型转换错误是功能上的差异。此外,当您不指定类型时,它会被推断出来。对于字符串,这意味着扩大到 NVARCHAR 的转换。如果您的表是 VARCHAR,则 SQL 将为查询的表中的每一行转换该列的值。这不会是一个错误,最终结果可能是相同的,但在功能上是不同的。

以上是关于Parameters.Add(string, object) 和 Parameters.AddWithValue 之间的区别的主要内容,如果未能解决你的问题,请参考以下文章

MySqlCommand Command.Parameters.Add 已过时

SQL UPDATE 命令不适用于 Command.Parameters.Add/AddWithValue [重复]

SqlCommand 参数 Add 与 AddWithValue [重复]

STRING TO HEX 如何在向量中添加 ob 字节?

SqlParameter 的使用

OleDb 参数语法