什么时候添加SqlCommand参数时应该使用“SqlDbType”和“size”?

有一个相关的问题:

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

但我想知道这些差异是什么,以及是否有不同的方式有任何问题。

我通常使用这样的结构:

using (SqlConnection conn = new SqlConnection(connectionString)) using (SqlCommand cmd = new SqlCommand(SQL, conn)) { cmd.CommandType = CommandType.Text; cmd.CommandTimeout = Settings.Default.reportTimeout; cmd.Parameters.Add("type", SqlDbType.VarChar, 4).Value = type; cmd.Connection.Open(); using (SqlDataAdapter adapter = new SqlDataAdapter(cmd)) { adapter.Fill(ds); } //use data } 

现在有几种方法来添加cmd参数,我想知道哪个是最好的:

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

在我所认为的varchars传递的字段长度不是可取的,因为它是一个魔法值,可能稍后在数据库中更改。 它是否正确? 它是否会导致以这种方式(性能或其他)传递varchar的任何问题,我认为它默认为varchar(max)或数据库等效。 我相当高兴这将工作。

更关注我的部分是SqlDbType枚举的丢失,如果我使用上面列出的第三个或第四个选项,我根本不提供types。 有没有情况下,这将无法正常工作我可以想象,varchar被错误地转换为字符或反之亦然的问题,也许小数到钱的问题….

就数据库而言,我所说的字段types比字段长度更不可能改变,所以值得保留呢?

根据我的经验,我会确保我做这些事情:

  • 确保它是你定义参数的数据types 。 ADO.NET在猜测方面做得不错,但在某些情况下,ADO.NET可能会非常糟糕 – 所以我会避免这种方法:

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

    让ADO.NET通过传递的值来猜测参数的types是非常棘手的,如果由于任何原因而closures的话,这些都是非常棘手的错误来跟踪和发现! 想象一下当你传入一个DBNull.Value时会发生什么 – ADO.NET应该select哪种数据types?

    只要明确 – 说出你想要什么types!

  • 如果你正在使用string参数,请确保明确定义长度 – 所以我也会避免这种方法:

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

    如果您不提供长度,ADO.NET可能会默认为某个任意值,或者将string的长度作为值传入,或者其他值 – 您从来不确定。 如果你的长度不符合存储过程的预期,你可能会看到转换和其他不愉快的意外。 所以如果你定义了一个string,也要定义它的长度!

所以在你的情况下,真正适用于我的唯一方法就是在这里:

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

因为它a)定义明确使用的数据types,b)明确地定义string的长度。

通过添加types,您的请求更有可能通过使用caching查询计划来提高性能。

以下是MSDN的一个引用:

参数化命令还可以提高查询执行性能,因为它们可以帮助数据库服务器将传入命令与适当的caching查询计划进行精确匹配。

在执行计划caching和重用中阅读更多内容。