将参数传递给 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(),但要注意隐式类型转换错误的可能性。

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

其他提示

里面发生了什么事?

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

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

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

的超载 Add 由于可能与 SqlParameterCollection.Add 超负荷 String 和一个 SqlDbType枚举值,其中通过字符串传递整数可以解释为参数值或相应的 SqlDbType 价值。使用 AddWithValue每当您想通过指定其名称和值来添加参数时。

构造函数重载为 SqlParameter 类仅仅是设置实例属性的便利。它们缩短了代码,对性能影响很小:构造函数可以绕过 setter 方法并直接对私有成员进行操作。如果有差别的话,也不会太大。

我应该怎么办?

请注意以下事项(来自 MSDN)

对于双向和输出参数以及返回值,您必须设置 Size. 。这对于输入参数不需要,如果未明确设置,则在执行参数化语句时从指定参数的实际大小中推断出该值。

默认类型是输入。但是,如果您允许像这样推断大小,并且在循环中回收参数对象(您确实说过您关心性能),那么大小将由第一个值设置,任何后续值更长将被设置被剪掉了。显然,这仅对于可变长度值(例如字符串)才有意义。

如果您在循环中重复传递相同的逻辑参数,我建议您在循环外部创建一个 SqlParameter 对象并适当调整其大小。增大 varchar 的大小是无害的,因此如果它是 PITA 以获得确切的最大值,只需将其设置为比您预期的列大即可。由于您要回收该对象而不是为每次迭代创建一个新对象,因此循环期间的内存消耗可能会 降低 即使您对超大尺寸感到有点兴奋。

说实话,除非您处理数千个呼叫,否则这些都不会产生太大影响。 AddWithValue 创建一个新对象,回避尺寸问题。它简短、甜蜜且易于理解。如果您循环数千次,请使用我的方法。如果不这样做,请使用 AddWithValue 使您的代码简单且易于维护。


2008年已经过去很久了

自从我写这篇文章以来的这些年里,世界已经发生了变化。有新的日期类型,而且还有一个问题一直没有出现在我的脑海中,直到最近的一个日期问题让我开始思考扩大日期的含义。

对于那些不熟悉这些术语的人来说,加宽和缩小是数据类型转换的性质。如果将 int 分配给 double,则不会损失精度,因为 double 更“宽”。这样做总是安全的,因此转换是自动的。这就是为什么您可以将 int 分配给 double,但反过来,您必须执行显式强制转换 - double 到 int 是一种缩小转换,可能会导致精度损失。

这适用于字符串:NVARCHAR 比 VARCHAR 更宽,因此您可以将 VARCHAR 分配给 NVARCHAR,但反之则需要强制转换。比较有效是因为 VARCHAR 隐式扩展为 NVARCHAR, 但这会干扰索引的使用!

C# 字符串是 Unicode,因此 AddWithValue 将生成 NVARCHAR 参数。在另一端,VARCHAR 列值扩展为 NVARCHAR 以进行比较。这不会停止查询执行,但会阻止使用索引。这不好。

你能为这个做什么?您有两种可能的解决方案。

  • 显式键入参数。这意味着不再需要 AddWithValue
  • 将所有字符串列类型更改为 NVARCHAR。

放弃 VARCHAR 可能是最好的主意。这是一个简单的更改,其后果可预测,并且可以改善您的本地化故事。但是,您可能没有这个选项。

这些天我没有做很多直接的 ADO.NET 工作。Linq2Sql 现在是我选择的武器,编写此更新的行为让我想知道它如何处理这个问题。我突然强烈地想要清除数据库中的 VARCHAR。

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

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

我曾经使用你的选项1:

  

cmd.Parameters.Add(<!> quot; @Name <!>;;,SqlDbType.VarChar,20).Value = <!> quot; Bob <!> quot ;;

工作正常,但后来我开始使用.AddWithValue,它就像它得到的一样简单。经过数千次使用后,它并没有给我带来麻烦。请注意,我几乎总是传递我的类私有变量,所以我不必担心隐式类型转换。

这取决于您的申请。我实际上喜欢2,因为如果我改变存储的proc参数的长度,我不会改变我的DAO。那只是我。我不知道是否有任何表现处罚或任何事情。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top