将parameter passing给SQLCommand的最佳方法是什么?

将parameter passing给SQLCommand的最佳方法是什么? 你可以做:

cmd.Parameters.Add("@Name", SqlDbType.VarChar, 20).Value = "Bob"; 

要么

 cmd.Parameters.Add("@Name", SqlDbType.VarChar).Value = "Bob"; 

要么

 cmd.Parameters.Add("@Name").Value = "Bob"; 

看起来第一个可能在某种程度上“更好”,无论是在性能方面还是在错误检查方面。 但是我想更确切地知道。

您也可以使用AddWithValue() ,但要注意隐式types转换的可能性。

 cmd.Parameters.AddWithValue("@Name", "Bob"); 

那里发生了什么?

您引用了几个重载的参数列表。 这些便利方法直接对应于SqlParameter类的构造函数重载。 他们基本上使用任何构造函数与您调用的便捷方法具有相同的签名来构造参数对象,然后像这样调用SqlParameterCollection.Add(SqlParameter)

 SqlParameter foo = new SqlParameter(parameterName, dbType, size); this.Add(foo); 

AddWithValue类似,但更方便,也设置值。 然而,它实际上是为解决框架缺陷而引入的。 引用MSDN,

由于可能带有SqlParameterCollection.Add重载的SqlParameterCollection.Add重载获取string和对象的重载,该重载需要一个String和一个SqlDbType枚举值,其中传递整数string可以被解释为参数值或对应的SqlDbType值。 只要您想通过指定名称和值来添加参数,就可以使用AddWithValue

SqlParameter类的构造函数重载仅仅是设置实例属性的方便之处。 他们缩短了代码,对性能的影响很小:构造函数可能会绕过setter方法,直接在私有成员上运行。 如果有差别就不会太多

我该怎么办?

请注意以下(来自MSDN)

对于双向和输出参数以及返回值,您必须设置Size的值。 这对于input参数不是必需的,如果没有明确设置,则在执行参数化语句时,根据指定参数的实际大小推断该值。

默认types是input。 但是,如果允许像这样推断大小,并且在循环中循环使用参数对象(您确实认为您关心的是性能),那么大小将由第一个值设置,随后的任何更长的值将会是裁剪。 显然这只对variables长度值如string有意义。

如果你在一个循环中重复传递相同的逻辑参数,我build议你在循环之外创build一个SqlParameter对象并且适当的调整它的大小。 超大尺寸的varchar是无害的,所以如果它是一个PITA来获得最大的精确度,那就把它设置得比你想象的要大。 因为你正在回收对象,而不是为每次迭代创build一个新对象,所以在循环的持续时间内,内存消耗可能会下降,即使你对超大尺寸感到兴奋。

真相被告知,除非你处理数千个电话,否则这些都不会有太大的改变。 AddWithValue创build一个新的对象,回避大小问题。 它简短而又甜美,易于理解。 如果你循环数千,请使用我的方法。 如果您不这样做,请使用AddWithValue使代码简单易维护。


2008年是很久以前的事了

自从我写这些以来,世界已经变了。 有一些新的date,也有一个问题,直到最近的date有问题,我才想到扩大的影响。

对于那些不熟悉这些术语的人来说,扩大和缩小是数据types转换的质量。 如果你把一个int赋给double,那么精度就不会丢失,因为double是“更宽”的。 这样做总是安全的,所以转换是自动的。 这就是为什么你可以分配一个int到一个双精度,但去另一种方式,你必须做一个明确的强制转换 – 双向int是一个缩小的转换,可能会失去精度。

这可以应用于string:NVARCHAR比VARCHAR更宽,因此您可以将VARCHAR分配给NVARCHAR,但以另一种方式需要投射。 比较工作,因为VARCHAR隐式扩大到NVARCHAR, 但这会干扰索引的使用!

C#string是Unicode的,所以AddWithValue将产生一个NVARCHAR参数。 另一方面,VARCHAR列值扩展为NVARCHAR进行比较。 这不会停止查询执行,但会阻止使用索引。 这不好。

你能做些什么呢? 你有两个可能的解决scheme。

  • 显式input参数。 这意味着没有更多的AddWithValue
  • 将所有string列types更改为NVARCHAR。

开沟VARCHAR可能是最好的主意。 这是一个简单的变化,具有可预见的后果,并改善了您的本地化故事。 但是,您可能没有这个选项。

这些天我不做很多直接的ADO.NET。 Linq2Sql现在是我select的武器,编写这个更新的行为让我想知道它是如何处理这个问题的。 我有一个突然,强烈的愿望来清除我的VARCHAR数据库。

我肯定会说#1。 但是,微软在企业库的数据访问应用程序块中是最好的,特别是SQL服务器:

http://msdn.microsoft.com/en-us/library/dd203144.aspx

我曾经使用你的选项1:

cmd.Parameters.Add(“@ Name”,SqlDbType.VarChar,20).Value =“Bob”;

这工作得很好,但后来我开始使用.AddWithValue,它是如此简单。 经过数千次的使用,它并没有造成我的问题。 请注意,我几乎总是通过我的类私有variables,所以我不必担心隐式types转换。

这取决于你的应用程序。 我其实喜欢2,因为如果我改变一个存储的proc参数的长度,我不需要改变我的DAO。 那只是我而已。 我不知道是否有任何performance处罚或任何东西。