Pet*_*ter 4 ado.net parameter c# sql-server-2016
最近我注意到我公司的应用程序使用AddWithValue
将参数值传递给动态的参数化查询。例子:
cmd.Parameters.AddWithValue("@VehicleId", Vehicles.VehicleId);
Run Code Online (Sandbox Code Playgroud)
在数据库中,该数据类型VehicleID
是INT
。
据我了解,由于 AddWithValue(已弃用)未指定数据类型/长度,因此此“@VehicleID”被转换并可能被错误转换。在“INT”的情况下,该转换是否会影响 SQL Server 性能?
这会导致计划缓存污染之外的问题吗?转换是否会导致性能下降?
Aar*_*and 11
我强烈建议始终使用允许您显式设置数据类型和精度的方法。是的,这需要更多的工作,无论是在前期还是数据库中的数据类型发生变化时(这很常见,例如,IDENTITY
列超出 的范围int
并将其升迁到bigint
)。
cmd.parameters.Add("@VehicleId", SqlDbType.Int).Value = Vehicles.VehicleId;
Run Code Online (Sandbox Code Playgroud)
这只是更好的做法,因为其他形式的AddWithValue()
可能会导致问题。例如,这里会推断出错误的类型:
cmd.parameters.AddWithValue("@intParam", 5); -- tinyint
cmd.parameters.AddWithValue("@intParam", 257); -- smallint
cmd.parameters.AddWithValue("@varchar20", "bob"); -- nvarchar(3)
cmd.parameters.AddWithValue("@varchar20", "frank"); -- nvarchar(5)
Run Code Online (Sandbox Code Playgroud)
在这个int
范围内,您不太可能遇到很多问题,但是如果您将其扩展到其他类型,并且使用临时查询而不是具有强类型参数的存储过程调用,事情会很快变得非常糟糕. 正如大卫指出的那样,您可能会得到糟糕的计划,例如可以使搜索切换到扫描的隐式转换。允许将默认值nvarchar
传递给varchar
列可能会导致严重的性能问题,正如Jonathan Kehayias 在此处演示的那样. 并且允许 .NET 根据字符串的长度来确定参数的长度可以(取决于 SQL Server 的版本和参数化设置)为传入的每个唯一长度的字符串生成不同的计划。这不会使那些特定查询速度较慢,但它们会浪费大量内存,因为每个长度都会存储和使用一个冗余计划。
这个问题在其他地方也有人问过:
而乔尔Coehoorn已经在博客类型转换的问题也建议你远离AddWithValue()
(甚至在情况下,你“知道”不存在这个问题):
在“INT”的情况下,该转换是否会影响 SQL Server 性能?
不可以。某些 .NET 数据类型完全映射到 SQL Server 数据类型,而 int 就是其中之一。并且这种方法不被弃用。请参阅此处的文档
因未准确指定参数类型而导致的问题通常仅限于糟糕的计划。如果传递的参数的数据类型优先级高于它映射到的列,则必须将列值转换为参数的类型以进行比较。这将阻止索引使用,并需要每行转换。
从值派生字符串参数类型的另一个问题是 .NET 的 SqlClient 会将参数的长度设置为传递的字符串的实际长度。这可以最大限度地减少网络流量和内存要求,但可以更改 SQL Server 中的查询计划缓存和重用行为。对于存储过程调用,这无关紧要,但对于临时 SQL 批处理,您最终可以为每个字符串长度使用不同的缓存计划。
如果您传递精度过高的数字/十进制参数,根据此处的规则,这可能会导致结果中的比例丢失,但参数通常不会出现在计算中。
归档时间: |
|
查看次数: |
2626 次 |
最近记录: |