有一个相关问题:
What's the best method to pass parameters to 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");
在我假设的变量传递中具有字段的长度是不可取的,因为它是可以在数据库中稍后更改的魔术值。它是否正确?它是否会导致以这种方式(性能或其他)传递varchar的任何问题,我假设它默认为varchar(max)或数据库等效。我很高兴这会奏效。
如果我使用上面列出的第三个或第四个选项,那么我更关心的部分是丢失SqlDbType枚举我根本不提供类型。有没有这种情况不起作用的情况我可以想象varchar被错误地转换为char或者反之亦然的问题,或者可能是带有小数的问题....
就数据库而言,我所说的字段类型更改的可能性远小于长度,因此值得保留吗?
答案 0 :(得分:55)
根据我的经验,我会确保我做这些事情:
确保为您定义参数的数据类型。 ADO.NET在猜测方面做得不错,但在某些情况下,它可能非常糟糕 - 所以我会避免使用这种方法:
cmd.Parameters.Add("@Name").Value = "Bob";
cmd.Parameters.AddWithValue("@Name", "Bob");
让ADO.NET通过传递的值来猜测参数的类型是棘手的,如果它因任何原因而关闭,那些跟踪和查找都是非常棘手的错误!想象一下当你传入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)明确定义字符串的长度。
答案 1 :(得分:6)
通过添加类型,您的请求更有可能通过使用缓存查询计划来提高性能。
以下是MSDN的引用:
参数化命令还可以提高查询执行性能,因为它们可以帮助数据库服务器将传入命令与正确的缓存查询计划精确匹配。
更多内容请阅读Execution Plan Caching and Reuse。