48

有一个相关的问题:

将参数传递给 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 枚举的丢失,我根本没有提供类型。在某些情况下这不起作用我可以想象 varchar 被错误地转换为 char 或反之亦然的问题,或者可能是小数转换为金钱的问题......

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

4

2 回答 2

62

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

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

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

    让 ADO.NET 通过传递的值来猜测参数的类型是很棘手的,如果它因任何原因而关闭,那么跟踪和查找这些 bug 真的很棘手!想象一下当你传入一个DBNull.Value- ADO.NET 应该为此选择什么数据类型时会发生什么?

    明确一点 - 说出你想要的类型!

  • 如果您使用的是字符串参数,请确保明确定义长度- 所以我也会避免使用这种方法:

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

    如果您不提供长度,ADO.NET 可能会默认为某个任意值,或者作为值传入的字符串的长度,或其他内容 - 您永远无法确定。如果您的长度与存储过程的实际期望不匹配,您可能会看到转换和其他令人不快的惊喜。所以如果你定义了一个字符串,也要定义它的长度!

所以在你的情况下,唯一对我有用的方法是这里的这个:

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

因为它 a) 显式定义了要使用的数据类型,并且 b) 显式定义了字符串的长度。

于 2011-01-07T11:10:54.503 回答
7

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

这是来自 MSDN 的引用:

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

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

于 2011-01-07T11:15:23.660 回答