一次往返执行多个SQL命令

时间:2010-02-25 17:58:45

标签: c# .net sql-server ado.net data-access

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

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

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

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

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

6 个答案:

答案 0 :(得分:37)

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

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());

    }
}

答案 1 :(得分:8)

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

修改:添加有关为什么将cram整合到一个电话中的信息。

虽然您不想太在意减少通话,但 可能是合法的原因。

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

答案 2 :(得分:2)

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

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

但是如果您的查询确实是您发布的内容(即选择所有用户,所有团队和所有权限),那么您显然已经拥有了在减少往返次数之前要更大的鱼来炸...先减少结果集。

答案 3 :(得分:1)

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

考虑使用至少相同的连接 - 打开;根据它所说的here,开放连接几乎是实体框架中性能成本的最高领导者。

答案 4 :(得分:0)

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

,如,

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

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

答案 5 :(得分:0)

首先,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

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