[转]实例化SqlParameter时,如果是字符型,一定要指定size属性

转自:http://bbs.csdn.net/topics/380155255

以前在实例化SqlParameter时,通常都是用下面的语句,没有设置size属性:

new SqlParameter("@name", SqlDbType.Varchar) { Value = name };

据MSDN解释:如果未在 size 参数中显式设置 Size,则从 dbType 参数的值推断出该大小。

我一直以为是从SqlDbType类型推断,实际上是从参数的值推断,比如"ab",则size值为2,"abcd",则size值为4,且经测试发现,size的值不同时,会导致执行计划不会重用,下面的代码:

string sql = "select top 1 * from tb where name = @o";
var para = new SqlParameter("@o", SqlDbType.VarChar) {Value = "ab"};
SqlHelper.ExecuteReader(ReadConnectionString, CommandType.Text, sql, para);

通过SqlProfiler捕获到的sql如下:

exec sp_executesql N'select top 1 * from tb where name = @o',N'@o nvarchar(2)',@o=N'ab'

如果把参数的值改成abcd,则通过SqlProfiler捕获到的sql如下:

exec sp_executesql N'select top 1 * from tb where name = @o',N'@o nvarchar(4)',@o=N'abcd'

通过下面的sql,可以看出执行计划是否有重用:

--先清空执行计划缓存
DBCC FREESYSTEMCACHE ('ALL')
DBCC FREEPROCCACHE
GO
SELECT * FROM sys.dm_exec_cached_plans WHERE cacheobjtype = 'Compiled Plan'
GO
exec sp_executesql N'select top 1 * from tb where name = @o',N'@o nvarchar(2)',@o=N'ab'
GO
SELECT * FROM sys.dm_exec_cached_plans WHERE cacheobjtype = 'Compiled Plan'
GO
exec sp_executesql N'select top 1 * from tb where name = @o',N'@o nvarchar(4)',@o=N'abcd'
GO
SELECT * FROM sys.dm_exec_cached_plans WHERE cacheobjtype = 'Compiled Plan'
GO

最后的说明,实例化SqlParameter时,如果是字符型,一定要指定size属性,如:

new SqlParameter("@name", SqlDbType.Varchar, 4000) { Value = name };

如果是Int、Float、Bigint之类的参数,可以不用指定size属性

再说明一下,如果用SqlDbType.Int之类的可以不用指定size属性的参数,但是size指定错误,可能出现无法预知的错误,具体原因还不确定,
正常情况下,SqlDbType.Int的size应该是4,如:

new SqlParameter("@name", SqlDbType.Int, 4) { Value = name };

我曾经误把这个size设置为20,结果测试未出现问题,发布到生产系统后,经常出现访问数据库超时的现象,因为测试环境无法重现,这个问题就搁置了

btw:SqlDbType.DateTime也不用指定size属性

posted @ 2017-03-29 23:17  liqipeng  阅读(293)  评论(6编辑  收藏  举报