将参数传递给SQLCommand的最佳方法是什么?你可以做:
cmd.Parameters.Add("@Name", SqlDbType.VarChar, 20).Value = "Bob";
要么
cmd.Parameters.Add("@Name", SqlDbType.VarChar).Value = "Bob";
要么
cmd.Parameters.Add("@Name").Value = "Bob";
看起来第一个可能在某种程度上"更好",无论是性能方面还是错误检查方式.但我想更清楚地知道.
您引用了几个重载的参数列表Add
.这些是直接对应于SqlParameter
类的构造函数重载的便捷方法.它们本质上构造参数对象,使用任何构造函数与您调用的方便方法具有相同的签名,然后调用SqlParameterCollection.Add(SqlParameter)
如下:
SqlParameter foo = new SqlParameter(parameterName, dbType, size); this.Add(foo);
AddWithValue
是类似的,但进一步方便,也设置值.然而,它实际上是为解决框架缺陷而引入的.引用MSDN,
它的重载
Add
需要一个字符串,并且一个对象被弃用,因为SqlParameterCollection.Add
重载可能存在歧义 ,它带有aString
和SqlDbType
枚举值,其中传递带字符串的整数可以被解释为参数值或相应的SqlDbType
值.使用AddWithValue
时,你想要通过指定名称和值添加一个参数.
类的构造函数重载SqlParameter
仅仅是设置实例属性的便利.它们缩短了代码,对性能产生了微不足道的影响:构造函数可以绕过setter方法并直接在私有成员上运行.如果有差异则不会太多.
请注意以下内容(来自MSDN)
对于双向和输出参数以及返回值,必须设置值
Size
.输入参数不需要这样做,如果没有显式设置,则在执行参数化语句时,从指定参数的实际大小推断出该值.
默认类型是输入.但是,如果您允许像这样推断大小并在循环中回收参数对象(您确实说您关注性能),那么大小将由第一个值设置,任何后续更长的值将是裁剪.显然,这仅对诸如字符串的可变长度值有意义.
如果在循环中重复传递相同的逻辑参数,我建议您在循环外创建一个SqlParameter对象并适当调整大小.过大的varchar是无害的,所以如果它是一个PITA来获得确切的最大值,只需将它设置得比你预期的那样大.因为您正在循环使用对象而不是为每次迭代创建一个新对象,所以即使您对超大尺寸感到有些兴奋,循环持续时间内的内存消耗也可能会下降.
说实话,除非你处理成千上万的电话,否则这些都不会产生太大的影响.AddWithValue
创建一个新对象,回避尺寸问题.它简短,甜美,易于理解.如果你循环数千,请使用我的方法.如果不这样做,请使用AddWithValue
以保持代码简单易用.
自从我写这篇文章以来,这个世界已经发生了变化.有新的日期,并且在最近的日期问题让我想到扩大的影响之前,还有一个问题没有出现在我脑海中.
对于那些不熟悉术语的人来说,扩大和缩小是数据类型转换的品质.如果为double分配int,则不会损失精度,因为double是"更宽"的.这样做总是安全的,因此转换是自动的.这就是为什么你可以将一个int分配给一个double但是另一个方法你需要进行一个显式的转换 - double to int是一个缩小的转换,可能会导致精度损失.
这可以应用于字符串:NVARCHAR比VARCHAR宽,因此您可以将VARCHAR分配给NVARCHAR,但是以另一种方式需要转换.比较有效,因为VARCHAR隐式扩展到NVARCHAR,但这会干扰索引的使用!
C#字符串是Unicode,因此AddWithValue将生成NVARCHAR参数.另一方面,VARCHAR列值扩展到NVARCHAR以进行比较.这不会停止查询执行,但会阻止使用索引.这是不好的.
你能为这个做什么?您有两种可能的解决方案.
显式键入参数.这意味着不再有AddWithValue
将所有字符串列类型更改为NVARCHAR.
Ditching VARCHAR可能是最好的主意.这是一个简单的变化,具有可预测的后果,它可以改善您的本地化故事.但是,您可能没有这个选项.
这几天我没有做很多直接的ADO.NET.Linq2Sql现在是我的首选武器,编写此更新的行为让我想知道它是如何处理这个问题的.我突然想要清除我的VARCHAR数据库.
您也可以使用AddWithValue()
,但要注意错误的隐式类型转换的可能性.
cmd.Parameters.AddWithValue("@Name", "Bob");
我肯定会说#1。但是,尽管Microsoft在企业库的数据访问应用程序块中做到了这一点,但是最好的选择是,尤其是对于SQL Server:
http://msdn.microsoft.com/en-us/library/dd203144.aspx