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

53

我阅读了MSDN文档和示例(此处),我知道 Parameters.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

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

5个回答

79

从功能上来说,它们没有区别。实际上,两者都会执行这个操作:

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,它选择了枚举重载。


唯一的问题是,您必须接受通过这种方式添加参数时会出现新警告的事实。 - phadaphunk
7
是的,警告是由于在文档中标明了此重载已过时。此外,根据文档所述,“当您使用此SqlParameterCollection.Add方法的重载来指定整数参数值时,请小心使用”。 - David Ruttka
如果有像我一样好奇的人,想知道为什么零可以隐式转换为枚举类型,但其他整数不行。这里有一个SO解释的链接:https://dev59.com/dGUp5IYBdhLWcg3w6q2q - an phu
也许我们应该将这个众所周知的答案与一些关于AddWithValue陷阱的更多信息整合在一起。https://blogs.msmvps.com/jcoehoorn/blog/2014/05/12/can-we-stop-using-addwithvalue-already/ 和 https://learn.microsoft.com/en-us/archive/msdn-magazine/2009/brownfield/how-data-access-code-affects-database-performance#duplicate=0 - Steve

10

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

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


3
不显式地提供类型,例如command.Parameters.Add("@ID", SqlDbType.Int);,它会尝试将输入隐式转换为其所期望的类型。
不好的一面是,隐式转换可能不是最优的转换,并且可能会导致性能下降。
这个话题的讨论在这里: http://forums.asp.net/t/1200255.aspx/1

2

当我们使用CommandObj.Parameter.Add()方法时,它需要两个参数,第一个是存储过程的参数,第二个是参数的数据类型;而.AddWithValue()方法需要两个参数,第一个是存储过程的参数,第二个是参数的值。

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

针对.AddWithValue方法

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

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


0

在功能方面没有区别


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

更多详细信息 请点击这里


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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接