MAW*_*656 15 c# sql database sql-server
所以在C#中使用存储过程我有如下代码(省略连接代码):
string sql = "GetClientDefaults";
SqlCommand cmd = new SqlCommand(sql);
cmd.CommandType = CommandType.StoredProcedure; //<-- DO I NEED THIS??
cmd.Parameters.AddWithValue("@computerName", computerName);
Run Code Online (Sandbox Code Playgroud)
其中sql是存储过程的名称.现在,这个代码似乎在有和没有注释行的情况下工作得很好.
那么,我需要这条线吗?设置它有一些性能(或其他)的好处吗?不设置或将其设置为文本是否有益处?
And*_*ren 15
根据此博客文章中的测试,SQL Server将为您执行参数化,方法是在使用时将语句包装在sp_executesql中CommandType.Text.但是当你使用时,CommandType.StoredProcedure你将参数化它,从而节省数据库的一些工作.后一种方法更快.
编辑:
建立
我自己做了一些测试,这是结果.
创建此过程:
create procedure dbo.Test
(
@Text1 varchar(10) = 'Default1'
,@Text2 varchar(10) = 'Default2'
)
as
begin
select @Text1 as Text1, @Text2 as Text2
end
Run Code Online (Sandbox Code Playgroud)
使用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"]);
}
}
}
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
结果
在这两种情况下,调用都是使用RPC进行的.
以下是跟踪显示的内容CommandType.Text:
exec sp_executesql N'dbo.Test',N'@Text1 nvarchar(5),@Text2 nvarchar(5)',@Text1=N'Text1',@Text2=N'Text2'
Run Code Online (Sandbox Code Playgroud)
以下是使用的结果CommandType.StoredProcedure:
exec dbo.Test @Text1=N'Text1',@Text2=N'Text2'
Run Code Online (Sandbox Code Playgroud)
正如您所看到的,文本调用包含在调用中,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'
Run Code Online (Sandbox Code Playgroud)
这意味着,当您使用时,CommandType.Text您必须将参数添加到CommandText除非您始终希望使用默认值.
所以,回答你的问题
CommandType.StoredProcedure速度更快.CommandType.Text,则必须将参数名称添加到对过程的调用中,除非您希望使用默认值.实际上存在巨大差异.如果指定命令类型,StoredProcedure则添加到SqlCommand的任何参数都将是添加过程调用的参数.如果将其保留为,Text则参数将添加到批处理中,而不是添加到过程中.为了说明这一点,让我们创建一个虚拟过程:
create procedure usp_test
@p1 char(10) = 'foo',
@p2 int = 42
as
select @p1, @p2;
go
Run Code Online (Sandbox Code Playgroud)
然后编译这个小小的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]);
}
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
结果是:
Type: Text Result: @p1: foo @p2: 42
Type: StoredProcedure Result: @p1: bar @p2: 24
Run Code Online (Sandbox Code Playgroud)
哎哟! 对于CommandType.Text设置虽然参数已传递给批处理,但它们未传递给过程.多小时调试乐趣的来源......
小智 6
您可以将其设置为允许ADO.NET帮助您.使用时CommandType.StoredProcedure,您必须将CommandText存储过程名称等于.
例如,这个:
YourSqlCommand.CommandType = CommandType.StoredProcedure;
YourSqlCommand.CommandText = "dbo.YourStoredProc";
Run Code Online (Sandbox Code Playgroud)
相当于:
YourSqlCommand.CommandText = "exec dbo.YourStoredProc";
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
18303 次 |
| 最近记录: |