根据
这篇博客文章中的测试,当你使用
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'
可以看到,文本调用被包装在一个 sp_executesql
的调用中,以便正确地进行参数化。当然,这样做会产生一些额外的开销,因此我之前说使用 CommandType.StoredProcedure
会更快速的说法仍然成立。
另一个值得注意的事情,也是一个关键问题,就是当我创建没有默认值的过程时,出现了以下错误:
Msg 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
中。
因此,回答你的问题:
- 使用
CommandType.StoredProcedure
更快。
- 如果你使用
CommandType.Text
,则必须在调用过程时添加参数名称,除非你希望使用默认值。
CommandType.StoredProcedure
会稍微更快。 - Andreas Ågren