Jos*_*osh 14 .net c# sql sql-server prepared-statement
我看了很多问题,但显然我的SO-fu不能胜任这个任务,所以我在这里.我试图有效地使用预准备语句,我不仅仅意味着参数化单个语句,而是编译一个语句以便重复使用多次.我的问题在于参数和重用以及如何正确实现.
一般来说,我遵循这个程序(人为的例子):
SqlConnection db = new SqlConnection(...);
SqlCommand s = new SqlCommand("select * from foo where a=@a", db);
s.Parameters.Add("@a", SqlDbType.VarChar, 8);
s.Prepare();
...
s.Parameters["@a"] = "bozo";
s.Execute();
Run Code Online (Sandbox Code Playgroud)
超级,有效.但是,每次运行此查询时,我都不想执行所有这些步骤(或后四个步骤).这似乎抵消了准备陈述的整个想法.在我看来,我只需要更改参数并重新执行,但问题是如何做到这一点?
我试过s.Parameters.Clear(),但这实际上删除了参数本身,而不仅仅是值,所以我基本上需要重新Add参数并再次重复Prepare,这似乎也打破了整个点.不用了,谢谢.
在这一点上,我留下迭代s.Parameters并将它们全部设置为null或其他值.它是否正确?不幸的是,在我目前的项目中,我有大约15个参数的查询需要执行〜每次运行10,000次.我可以将这个迭代分流成一个方法但是想知道是否有更好的方法来做到这一点(没有存储过程).
我目前的解决方法是一个扩展方法,SqlParameterCollection.Nullify它将所有参数设置为null,这对我的情况很好.我只是在执行后运行它.
我发现了一些几乎完全相同但(恕我直言)尚未解答的问题:
SQLite/C#连接池和准备语句混淆(Serge非常接近回答!)
我能找到的最佳答案是(1)上面的常识和(2)这个页面:
sim*_*rcl 10
重新使用准备好的SqlCommand时,您当然需要将参数值设置为新值吗?使用后您无需清除它们.
对于我自己,我没有看到过去10年中生成的DBMS,它从准备语句中获得了明显的好处(我想如果数据库服务器可能处于其CPU的极限,但这不是典型的).你确定准备是必要的吗?
除非你从外部源上传,否则运行相同的命令"每次运行~10,000次"对我来说有点香味.在这种情况下,批量加载可能有帮助吗?每次跑步都在做什么?
干杯 -
为了增加Simon的答案,在Sql 2005之前, Command.Prepare()将改进对ad-hoc查询的查询计划缓存(通常会编译SPROC).但是,在更新的Sql版本中,只要您的查询已参数化,也可以缓存也参数化的即席查询,从而减少对查询的需求Prepare().
下面是一个保留SqlParameters集合的示例,只更改那些变化的参数值的值,以防止重复创建参数(即保存参数对象的创建和收集):
using (var sqlConnection = new SqlConnection("connstring"))
{
sqlConnection.Open();
using (var sqlCommand = new SqlCommand
{
Connection = sqlConnection,
CommandText = "dbo.MyProc",
CommandType = CommandType.StoredProcedure,
})
{
// Once-off setup per connection
// This parameter doesn't vary so is set just once
sqlCommand.Parameters.Add("ConstantParam0", SqlDbType.Int).Value = 1234;
// These parameters are defined once but set multiple times
sqlCommand.Parameters.Add(new SqlParameter("VarParam1", SqlDbType.VarChar));
sqlCommand.Parameters.Add(new SqlParameter("VarParam2", SqlDbType.DateTime));
// Tight loop - performance critical
foreach(var item in itemsToExec)
{
// No need to set ConstantParam0
// Reuses variable parameters, by just mutating values
sqlParameters["VarParam1"].Value = item.Param1Value; // Or sqlParameters[1].Value
sqlParameters["VarParam2"].Value = item.Param2Date; // Or sqlParameters[2].Value
sqlCommand.ExecuteNonQuery();
}
}
}
Run Code Online (Sandbox Code Playgroud)
笔记: