根据this blog post 中的测试,当您使用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 更快的说法仍然成立。
另一件值得注意的事情,这也是一个交易破坏者,当我创建没有默认值的过程时,我得到了以下错误:
消息 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,则必须将参数名称添加到对过程的调用中,除非您希望使用默认值。