AddWithValue难度

Car*_*don 0 .net sql sql-server

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

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

生成此sql命令:

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

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

SELECT * FROM table WHERE table.name = 'A String'
Run Code Online (Sandbox Code Playgroud)

第二个查询执行我期望的,我希望两个查询返回相同的结果.

我在代码中做错了什么?

Rem*_*anu 5

Profiler没有说谎,它说你传递的是带有值的参数@A=A string.那不同于A String.这意味着您可能正在添加如下参数:

cmd.Parameters.AddWithValue("@A", "@A=A string");
Run Code Online (Sandbox Code Playgroud)

更新

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