读书人

经验分享:实例化SqlParameter时如果

发布时间: 2012-06-11 17:42:22 作者: rapoo

经验分享:实例化SqlParameter时,如果是字符型,一定要指定size属性
以前在实例化SqlParameter时,通常都是用下面的语句,没有设置size属性:

C# code
new SqlParameter("@name", SqlDbType.Varchar) { Value = name };
根据MSDN解释:如果未在 size 参数中显式设置 Size,则从 dbType 参数的值推断出该大小。
我一直以为是从SqlDbType类型推断,实际上是从参数的值推断,比如"ab",则size值为2,"abcd",则size值为4,且经测试发现,size的值不同时,会导致执行计划不会重用,下面的代码:
C# code
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如下:
SQL code
exec sp_executesql N'select top 1 * from tb where name = @o',N'@o nvarchar(2)',@o=N'ab'
如果把参数的值改成abcd,则通过SqlProfiler捕获到的sql如下:
SQL code
exec sp_executesql N'select top 1 * from tb where name = @o',N'@o nvarchar(4)',@o=N'abcd'
通过下面的sql,可以看出执行计划是否有重用:
SQL code
--先清空执行计划缓存DBCC FREESYSTEMCACHE ('ALL')DBCC FREEPROCCACHEGOSELECT * FROM sys.dm_exec_cached_plans WHERE cacheobjtype = 'Compiled Plan'GOexec sp_executesql N'select top 1 * from tb where name = @o',N'@o nvarchar(2)',@o=N'ab'GOSELECT * FROM sys.dm_exec_cached_plans WHERE cacheobjtype = 'Compiled Plan'GOexec sp_executesql N'select top 1 * from tb where name = @o',N'@o nvarchar(4)',@o=N'abcd'GOSELECT * FROM sys.dm_exec_cached_plans WHERE cacheobjtype = 'Compiled Plan'GO

最后的说明,实例化SqlParameter时,如果是字符型,一定要指定size属性,如:
C# code
new SqlParameter("@name", SqlDbType.Varchar, 4000) { Value = name };
如果是Int、Float、Bigint之类的参数,可以不用指定size属性


[解决办法]
嗯,受教了,以前还真没注意过
[解决办法]
不错,
[解决办法]
int之类的可以不用指定,但float,decimal之类的需要指定
[解决办法]
C# code
分享必属极品,感谢楼主分享。
[解决办法]
学无止境
[解决办法]
受教了
[解决办法]
SQL code
SELECT est.text AS batchtext, SUBSTRING(est.text, (eqs.statement_start_offset/2)+1,  (CASE eqs.statement_end_offset WHEN -1  THEN DATALENGTH(est.text)  ELSE eqs.statement_end_offset END -  ((eqs.statement_start_offset/2) + 1))) AS querytext, eqs.creation_time, eqs.last_execution_time, eqs.execution_count,  eqs.total_worker_time, eqs.last_worker_time,  eqs.min_worker_time, eqs.max_worker_time,  eqs.total_physical_reads, eqs.last_physical_reads,  eqs.min_physical_reads, eqs.max_physical_reads,  eqs.total_elapsed_time, eqs.last_elapsed_time,  eqs.min_elapsed_time, eqs.max_elapsed_time,  eqs.total_logical_writes, eqs.last_logical_writes,  eqs.min_logical_writes, eqs.max_logical_writes, eqs.query_plan_hash FROM sys.dm_exec_query_stats AS eqs CROSS APPLY sys.dm_exec_sql_text(eqs.sql_handle) AS estORDER BY eqs.total_physical_reads DESC 


[解决办法]
支持LZ的探寻与验证的精神,赞个
[解决办法]

探讨
C# code
分享必属极品,感谢楼主分享。

[解决办法]
嗯,受教了.谢谢.
[解决办法]
嗯,受教了.谢谢.
[解决办法]
老赵的文章里提到过。up
[解决办法]
C# code
最好指定 否则会引起不必要的麻烦
[解决办法]
探讨
不需要,我测试过,如:

C# code

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

得到的sql是:

SQL code

exec sp_executesql N'select top 1 * from tb where name = @o',N'@o FLOAT',@o=1.2



……

[解决办法]
应用程序错误啊 哎
[解决办法]
微软就是会折腾人,这要是换做Oracle,根本不需要指定,因为Oracle的输入参数,varchar2类型是不带长度的,因此你是否指定一个固定的长度,都不会影响所谓的执行计划(SQL缓存)。
[解决办法]
还有一种情况必须说明,如果你是执行存储过程,参数长度也不必指定,因为那个是由存储过程参数定义的,你实际参数的长度必须转换到存储过程声明的参数长度,这时也就不存在任何效率问题。而实际传参数多数是用在存储过程中,非存储过程一般直接拼接SQL。
[解决办法]
不明白为什么,先收藏以防不时只需
[解决办法]

[解决办法]
啊多少反而范德萨 是地方撒
[解决办法]
范德萨爱封是
[解决办法]
学习了
[解决办法]
谢谢分享
[解决办法]
学习了,楼主辛苦了
[解决办法]
跟着学习
[解决办法]
这样啊 谢谢楼主
[解决办法]
谢谢楼主分享
[解决办法]
习惯做法
C# code
new SqlParameter("@UserID", SqlDbType.BigInt,19,ParameterDirection.Input,false,8,0,"",DataRowVersion.Current,model.UserID)//,new SqlParameter("@Name", SqlDbType.NVarChar,20,ParameterDirection.Input,false,0,0,"",DataRowVersion.Current,model.Name)//,new SqlParameter("@Password", SqlDbType.Decimal,18,ParameterDirection.Input,true,9,2,"",DataRowVersion.Current,model.Password)//,new SqlParameter("@UnitID", SqlDbType.DateTime,23,ParameterDirection.Input,true,8,3,"",DataRowVersion.Current,model.UnitID)//,new SqlParameter("@Reserved", SqlDbType.Bit,1,ParameterDirection.Input,true,1,0,"",DataRowVersion.Current,model.Reserved)//
[解决办法]
我一般都是不指定字符串大小。。看来对性能影响不小!
[解决办法]
虽然不明白楼主在说什么,但是感觉楼主很牛B
------解决方案--------------------


int当然只能到4了,int32 =4*8
[解决办法]

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

C# code

new SqlParameter("@name", SqlDbType.Varchar) { Value = name };
根据MSDN解释:如果未在 size 参数中显式设置 Size,则从 dbType 参数的值推断出该大小。
我一直以为是从SqlDbType类型推断,实际上……

[解决办法]
说的没错,不过使用sqlhelper的语法会更简单哦!新版本去http://www.dbhelper.org/sqlhelper/下载吧
[解决办法]
探讨

哦,有空测试下看看

btw:size千万别设置太小了,我也吃过这方面的亏,比如size设置为1,参数值为abc,结果只会传递一个a进去,我曾经查了半天,一直没有注意到这个1……

引用:
引用:
不需要,我测试过,如:

C# code

new SqlParameter("@name", SqlDbType.F……

[解决办法]
以前从来不设的,现在看来需要设一下
[解决办法]
这个问题可能我已经遇到N次了,以前经常出现网站无法访问,一直没有找到原因。。。

很可能就是楼主说的这个问题。。。

谢啦。。。
[解决办法]
多谢,
看了你的文章感觉我的路还长着
[解决办法]
学习了!!
[解决办法]
了。
[解决办法]
学习了。

读书人网 >C#

热点推荐