在一次往返中执行多个SQL命令

我正在构建一个应用程序,我想将多个查询批处理到数据库的单个往返。 例如,假设单个页面需要显示用户列表,组列表和权限列表。

所以我存储了procs(或者只是简单的sql命令,比如“select * from Users”),我想执行其中的三个。 但是,为了填充这一页,我必须进行3次往返。

现在我可以编写单个存储过程(“getUsersTeamsAndPermissions”)或执行单个SQL命令“select * from Users; exec getTeams; select * from Permissions”。

但我想知道是否有更好的方法来指定在一次往返中进行3次操作。 好处包括更容易进行unit testing,并允许数据库引擎将查询并行化。

我正在使用C#3.5和SQL Server 2008。

您提到的单个多部分命令和存储过程选项是两个选项。 您无法以这样的方式执行它们,即它们在数据库上“并行化”。 但是,这两个选项都会导致单次往返 ,所以你在那里很好。 没有办法更有效地发送它们。 在sql server 2005及更高版本中,完全参数化的多部分命令非常有效。

编辑 :添加有关为什么填写单个呼叫的信息。

虽然你不想太在意减少通话,但可能有正当理由。

  • 我曾经被限制在针对大型机的一个糟糕的ODBC驱动程序,并且每次调用都有1.2秒的开销! 我是认真的。 有时候我把一些额外的东西塞进我的db调用中。 不漂亮。
  • 您可能还会发现自己处于必须在某处配置SQL查询的情况,并且您不能只进行3次调用:它必须是一个。 不应该那样,糟糕的设计,但确实如此。 你做你要做的事!
  • 有时,将多个步骤封装在存储过程中当然是非常好的。 通常不是为了保存往返,而是为了更紧密的交易,获取新记录的ID,限制权限,提供封装,等等等等。 ( 但请不要一直开始使用存储过程。 )

像这样的东西。 这个例子可能不是很好,因为它没有正确处理对象,但你明白了。 这是一个清理版本:

using (var connection = new SqlConnection(ConnectionString)) using (var command = connection.CreateCommand()) { connection.Open(); command.CommandText = "select id from test1; select id from test2"; using (var reader = command.ExecuteReader()) { do { while (reader.Read()) { Console.WriteLine(reader.GetInt32(0)); } Console.WriteLine("--next command--"); } while (reader.NextResult()); } } 

进行一次往返对比三次确实会更有效。 问题是值得麻烦的。 整个ADO.Net和C#3.5工具集和框架都反对您尝试的操作。 TableAdapters,Linq2SQL,EF,所有这些都喜欢处理简单的one-call == one-resultset语义。 因此,通过尝试击败框架提交,您可能会失去一些严重的生产力。

我会说,除非你有一些严肃的测量表明你需要减少往返次数,否则弃权。 如果你最终要求这样 ,那么使用存储过程至少给出API类型的语义。

但是如果您的查询确实是您发布的内容(即选择所有用户, 所有团队和所有权限),那么在减少往返之前,您可能会有更大的鱼来煎炸…首先减少结果集。

我这个链接可能会有所帮助。

考虑至少使用相同的连接 – 打开; 根据它在这里所说的,开放连接几乎是entity framework中性能成本的最高领导者。

首先,3次往返并不是什么大不了的事。 如果你正在谈论300次往返那么这将是另一回事,但对于仅仅3次往返我会认为这是definitley是一个过早优化的情况。

也就是说,我这样做的方式可能是使用SQL执行3个存储的procuedres:

 exec dbo.p_myproc_1 @param_1 = @in_param_1, @param_2 = @in_param_2 exec dbo.p_myproc_2 exec dbo.p_myproc_3 

然后,您可以像直接执行多个行集一样遍历返回的结果集。

建一个临时表? 将所有结果插入临时表,然后select * from @temp-table

如,

 @temptable=.... select @temptable.field=mytable.field from mytable select @temptable.field2=mytable2.field2 from mytable2 

等…只有一次数据库之旅,但我不确定它实际上更有效率。