执行存储过程时,使用CommandType.StoredProcedure与使用CommandType.Text有什么好处?
所以在C#中使用存储过程我有如下代码(省略连接代码):
string sql = "GetClientDefaults"; SqlCommand cmd = new SqlCommand(sql); cmd.CommandType = CommandType.StoredProcedure; //<-- DO I NEED THIS?? cmd.Parameters.AddWithValue("@computerName", computerName);
其中sql是存储过程的名称。 现在,这个代码似乎在有和没有注释行的情况下工作得很好。
那么,我需要这条线吗? 设置这个有一些表现(或其他)好处吗? 不设置或将其设置为文本有什么好处?
根据此博客文章中的测试,当您使用CommandType.Text
时,SQL Server将通过将语句包装在sp_executesql中来为您执行参数化。 但是当您使用CommandType.StoredProcedure
您将对其进行参数化,从而为数据库保存一些工作。 后一种方法更快。
编辑:
建立
我自己做了一些测试,这是结果。
创建此过程:
create procedure dbo.Test ( @Text1 varchar(10) = 'Default1' ,@Text2 varchar(10) = 'Default2' ) as begin select @Text1 as Text1, @Text2 as Text2 end
使用SQL Server Profiler向其添加跟踪。
然后使用以下代码调用它:
using System; using System.Data; using System.Data.SqlClient; namespace ConsoleApplication2 { class Program { static void Main() { CallProcedure( CommandType.Text ); CallProcedure( CommandType.StoredProcedure ); } private static void CallProcedure(CommandType commandType) { using ( SqlConnection connection = new SqlConnection("Data Source=localhost;Initial Catalog=Test;Integrated Security=SSPI;") ) { connection.Open(); using ( SqlCommand textCommand = new SqlCommand("dbo.Test", connection) ) { textCommand.CommandType = commandType; textCommand.Parameters.AddWithValue("@Text1", "Text1"); textCommand.Parameters.AddWithValue("@Text2", "Text2"); using ( IDataReader reader = textCommand.ExecuteReader() ) { while ( reader.Read() ) { Console.WriteLine(reader["Text1"] + " " + reader["Text2"]); } } } } } } }
结果
在这两种情况下,调用都是使用RPC进行的。
以下是跟踪使用CommandType.Text
显示的内容:
exec sp_executesql N'dbo.Test',N'@Text1 nvarchar(5),@Text2 nvarchar(5)',@Text1=N'Text1',@Text2=N'Text2'
这是使用CommandType.StoredProcedure
的结果:
exec dbo.Test @Text1=N'Text1',@Text2=N'Text2'
正如您所看到的,text-call包含在对sp_executesql
的调用中,以便正确地进行参数化。 这当然会产生轻微的开销,因此我之前使用CommandType.StoredProcedure
更快的声明仍然有效。
另一个值得注意的事情,也就是这里的交易破坏者,当我创建没有默认值的过程时,我得到以下错误:
消息201,级别16,状态4,过程测试,行0过程或函数’测试’期望参数’@ Text1’,未提供。
这样做的原因是如何创建对sp_executesql
的调用,因为您可以看到参数已声明并初始化, 但它们未被使用 。 对于工作电话,它应该看起来像这样:
exec sp_executesql N'dbo.Test @Text1, @Text2',N'@Text1 nvarchar(5),@Text2 nvarchar(5)',@Text1=N'Text1',@Text2=N'Text2'
这意味着,当您使用CommandType.Text
您必须将参数添加到CommandText
除非您始终希望使用默认值。
所以,回答你的问题
- 使用
CommandType.StoredProcedure
更快。 - 如果您正在使用
CommandType.Text
,那么除非您希望使用默认值,否则您必须将参数名称添加到对过程的调用中。
您可以将其设置为允许ADO.NET帮助您。 当您使用CommandType.StoredProcedure
,您必须将CommandText
等于存储过程名称。
例如,这个:
YourSqlCommand.CommandType = CommandType.StoredProcedure; YourSqlCommand.CommandText = "dbo.YourStoredProc";
相当于:
YourSqlCommand.CommandText = "exec dbo.YourStoredProc";
实际上存在巨大差异。 如果指定命令类型StoredProcedure
则添加到SqlCommand的任何参数都将是添加过程调用的参数。 如果将其保留为Text
则参数将添加到批处理中 ,而不是添加到过程中。 为了说明这一点,让我们创建一个虚拟过程:
create procedure usp_test @p1 char(10) = 'foo', @p2 int = 42 as select @p1, @p2; go
然后编译这个小小的C#应用程序:
static void Main(string[] args) { ExecWithType(CommandType.Text); ExecWithType(CommandType.StoredProcedure); } static void ExecWithType(CommandType type) { using (SqlConnection conn = new SqlConnection(Settings.Default.connString)) { conn.Open(); using (SqlCommand cmd1 = new SqlCommand("usp_test", conn)) { cmd1.CommandType = type; cmd1.Parameters.AddWithValue("@p1", "bar"); cmd1.Parameters.AddWithValue("@p2", 24); using (SqlDataReader rdr = cmd1.ExecuteReader()) { while (rdr.Read()) { Console.WriteLine("Type: {0} Result: @p1: {1} @p2: {2}", type, rdr[0], rdr[1]); } } } } }
结果是:
Type: Text Result: @p1: foo @p2: 42 Type: StoredProcedure Result: @p1: bar @p2: 24
哎哟! 对于CommandType.Text
设置,尽管参数已传递给批处理 ,但它们未传递给该过程 。 多小时调试乐趣的来源……
CommandType不是特定于SQL Server。 它是IDbCommand接口的一个属性,它指示底层提供程序以特定方式处理CommandText。 虽然SQL Server可能会将单字名称视为过程,但您不应期望这在其他提供程序中起作用。
通常,您应该更喜欢使用提供程序生成的类(如DbCommand)而不是像SqlCommand这样的特定类。 这样,您只需更改配置文件中的提供程序字符串即可定位不同的数据库。
上述就是C#学习教程:执行存储过程时,使用CommandType.StoredProcedure与使用CommandType.Text有什么好处?分享的全部内容,如果对大家有所用处且需要了解更多关于C#学习教程,希望大家多多关注—计算机技术网(www.ctvol.com)!
本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。
ctvol管理联系方式QQ:251552304
本文章地址:https://www.ctvol.com/cdevelopment/1001524.html