根据测试这篇博文 http://sqlblog.com/blogs/tibor_karaszi/archive/2010/01/11/is-there-and-overhead-to-rpc-events.aspx当您使用时,SQL Server 将通过将语句包装在 sp_executesql 中来为您进行参数化CommandType.Text
。但是当你使用CommandType.StoredProcedure
您将对其进行参数化,从而节省数据库的一些工作。后一种方法更快。
Edit:
Setup
我自己做了一些测试,结果如下。
创建此过程:
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"]);
}
}
}
}
}
}
}
Results
在这两种情况下,调用都是使用 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'
正如您所看到的,文本调用包含在对sp_executesql
以便对其进行正确的参数化。这当然会产生轻微的开销,因此我之前的声明是使用CommandType.StoredProcedure
更快仍然成立。
另一个值得注意的事情,也是这里的一个交易破坏者,是当我创建没有默认值的过程时,我收到以下错误:
消息 201,级别 16,状态 4,程序测试,第 0 行程序或
函数“Test”需要参数“@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
除非您总是希望使用默认值。
所以,回答你的问题
- Using
CommandType.StoredProcedure
是比较快的。
- 如果您正在使用
CommandType.Text
,那么您必须将参数名称添加到对过程的调用中,除非您希望使用默认值。