AddWithValue难度

时间:2009-09-03 17:21:45

标签: .net sql sql-server

我想用.NET运行参数化SQL。但是当我使用AddWithValue()时,生成的命令不起作用。

SqlCommand cmd = new SqlCommand("SELECT * FROM table WHERE table.name = @A")
cmd.Parameters.AddWithValue("@A", "A string");

生成此sql命令:

exec sp_executesql N'SELECT * FROM table WHERE table.name = @A',N'@A nvarchar(10)',@A=N'''A string'''

但是该命令不返回任何值,而以下命令返回我想要的值(即匹配一行):

SELECT * FROM table WHERE table.name = 'A String'

第二个查询完成了我的预期,我希望两个查询都返回相同的结果。

我在代码中做错了什么?

1 个答案:

答案 0 :(得分:5)

Profiler没有说谎,它说您传入的值为@A=A string的参数。这与A String不同。这意味着您可能正在添加如下参数:

cmd.Parameters.AddWithValue("@A", "@A=A string");

<强>更新

修好帖子后。测试和sql_executesql实际上仍然不同。这次差异很微妙:参数是Unicode类型!这意味着查询必须执行从Name列类型(可能是Varchar)到Unicode(Nvarchar)的转换。此转换将考虑您对列的排序规则,并且可能会导致其他内容超出预期。作为副作用,它还使查询不具有SARG能力(即使Name具有索引,也将扫描整个表!)。 AddWithValue创建NVARCHAR类型参数的事实是一个已知的陷阱,这就是为什么大多数退伍军人都会避免这种情况。它还创建类型长度的参数,与参数长度完全相同(即NVARCHAR(10)),因为查询计划依赖于参数 types ,而NVARCHAR(10)是不同的类型< / em>比NVARCHAR(11),这导致糟糕的计划缓存重用,更高的编译时间和缓存压缩。这两个问题的解决方案是在CLR中使用显式创建的参数,并控制参数SqlDbType和length(即始终使用列长度)。我知道的“快速发展”不如AddWithValue,但不幸的是,现在这是ADO.Net的事态。