Podle testů v tomto blogovém příspěvku SQL Server provede parametrizaci za vás zabalením vašeho příkazu do sp_executesql, když použijete CommandType.Text
. Ale když použijete CommandType.StoredProcedure
budete ji parametrizovat a tím databázi ušetříte práci. Druhá metoda je rychlejší.
Upravit:
Nastavení
Sám jsem provedl nějaké testy a zde jsou výsledky.
Vytvořte tento postup:
create procedure dbo.Test
(
@Text1 varchar(10) = 'Default1'
,@Text2 varchar(10) = 'Default2'
)
as
begin
select @Text1 as Text1, @Text2 as Text2
end
Přidejte k němu trasování pomocí SQL Server Profiler.
A pak jej zavolejte pomocí následujícího kódu:
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"]);
}
}
}
}
}
}
}
Výsledky
V obou případech jsou hovory prováděny pomocí RPC.
Zde je to, co trasování odhalí pomocí CommandType.Text
:
exec sp_executesql N'dbo.Test',N'@Text1 nvarchar(5),@Text2 nvarchar(5)',@Text1=N'Text1',@Text2=N'Text2'
A zde je výsledek pomocí CommandType.StoredProcedure
:
exec dbo.Test @Text1=N'Text1',@Text2=N'Text2'
Jak můžete vidět, textové volání je zabaleno do volání sp_executesql
aby byl správně parametrizován. To samozřejmě způsobí mírnou režii, a tudíž mé předchozí tvrzení, že použití CommandType.StoredProcedure
je rychlejší stále stojí.
Další věc, která stojí za zmínku, a která je zde také určitým způsobem narušující dohodu, je to, že když jsem vytvořil proceduru bez výchozích hodnot, dostal jsem následující chybu:
Zpráva 201, Úroveň 16, Stav 4, Test procedury, řádek 0 Procedura nebo funkce 'Test' očekává parametr '@Text1', který nebyl dodán.
Důvodem je způsob volání sp_executesql
je vytvořen, jak vidíte, parametry jsou deklarovány a inicializovány, ale nejsou použity . Aby hovor fungoval, měl vypadat takto:
exec sp_executesql N'dbo.Test @Text1, @Text2',N'@Text1 nvarchar(5),@Text2 nvarchar(5)',@Text1=N'Text1',@Text2=N'Text2'
To znamená, když používáte CommandType.Text
musíte přidat parametry do CommandText
pokud nechcete, aby byly vždy použity výchozí hodnoty.
Abych tedy odpověděl na vaši otázku
- Pomocí
CommandType.StoredProcedure
je rychlejší. - Pokud používáte
CommandType.Text
, pak budete muset přidat názvy parametrů do volání procedury, pokud nechcete, aby byly použity výchozí hodnoty.