里面在发生什么?
您引用了几个Add
的重载参数列表。这些是方便方法,直接对应于SqlParameter
类的构造函数重载。它们基本上使用与您调用的方便方法具有相同签名的任何构造函数来构造参数对象,然后像这样调用SqlParameterCollection.Add(SqlParameter)
:
SqlParameter foo = new SqlParameter(parameterName, dbType, size)
this.Add(foo)
AddWithValue
方法与
Add
类似,但更加方便,可以设置参数值。然而,它实际上是为了解决框架缺陷而引入的。引用MSDN所说,
“因为通过传递整数和字符串可能会被解释为参数值或相应的SqlDbType值之一,所以
Add
方法的一个重载已经被弃用,该方法接受字符串和对象作为参数。使用
AddWithValue
来指定参数名称和值添加参数。”
SqlParameter
类的构造函数重载仅用于设置实例属性的方便性。它们缩短了代码,对性能影响很小:构造函数可能会绕过设置器方法并直接操作私有成员。如果有差异,那也不会太大。
要注意以下内容(来自MSDN):
“对于双向和输出参数以及返回值,必须设置
Size
的值。对于输入参数则不需要,如果没有显式设置,则在执行参数化语句时会从指定参数的实际大小中推断出该值。”
默认类型是输入。然而,如果像这样允许大小被推断,而且在循环中重复使用参数对象(您说您关心性能),则大小将由第一个值设置,并且任何后续的比此更长的值都将被截断。显然,这只对可变长度值(如字符串)有意义。
如果在循环中重复传递相同的逻辑参数,我建议您在循环外创建一个 SqlParameter 对象,并适当调整其大小。过度设置 varchar 是无害的,因此如果您难以获得精确的最大值,请将其设置为比您预计该列要大。由于您正在回收对象而不是为每个迭代创建新对象,因此即使您过度调整大小,内存消耗在循环期间也可能会减少。
说实话,除非您处理数千个调用,否则所有这些都不会产生太大的差异。
AddWithValue
创建一个新对象,避开了大小问题。它简短易懂,容易理解。如果您需要循环执行数千次,则使用我的方法。如果不是,请使用
AddWithValue
使您的代码简单易于维护。
自从我写下这篇文章以来,2008年已经过去很久了。世界发生了变化。有了新的日期类型,直到最近日期出现问题才让我考虑到扩展的影响。
对于那些不熟悉术语的人来说,扩展和收缩是数据类型转换的特性。如果将 int 分配给 double,则不会丢失精度,因为 double 更宽。这样做始终是安全的,因此转换是自动的。这就是为什么可以将 int 分配给 double,但反过来必须进行显式转换——double 到 int 是一种收缩转换,可能会丢失精度。
这也适用于字符串:NVARCHAR 比 VARCHAR 更宽,因此可以将 VARCHAR 分配给 NVARCHAR,但反过来则需要进行转换。比较起来是有效的,因为 VARCHAR 隐式扩展到 NVARCHAR,但这将干扰索引的使用!
C# 字符串是 Unicode 的,因此 AddWithValue 将生成一个 NVARCHAR 参数。在另一端,VARCHAR 列值扩展到 NVARCHAR 进行比较。这不会阻止查询执行,但会阻止索引的使用。这很糟糕。
您可以采取什么