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

C# 在一次往返中执行多个SQL命令,c#,.net,sql-server,ado.net,data-access,C#,.net,Sql Server,Ado.net,Data Access,我正在构建一个应用程序,希望将多个查询批处理到数据库的一个往返过程中。例如,假设单个页面需要显示用户列表、组列表和权限列表 所以我从用户那里存储了proc或者简单的sql命令,比如select*,我想执行其中三个。然而,要填充这一页,我必须进行3次往返 现在我可以编写一个存储过程getUsersTeamsAndPermissions,或者从用户处执行一个SQL命令select*;执行团队;从权限中选择* 但我想知道是否有更好的方法来指定在一次往返中执行3个操作。好处包括易于单元测试,并允许数据库

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

所以我从用户那里存储了proc或者简单的sql命令,比如select*,我想执行其中三个。然而,要填充这一页,我必须进行3次往返

现在我可以编写一个存储过程getUsersTeamsAndPermissions,或者从用户处执行一个SQL命令select*;执行团队;从权限中选择*

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

我使用的是C 3.5和SQL Server 2008。

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

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

    }
}

您提到的单个多部分命令和存储过程选项是两个选项。您不能以在db上并行的方式执行它们。然而,这两种选择都会导致一次往返,所以你在这方面做得很好。没有办法更有效地发送它们。在SQLServer2005以后的版本中,完全参数化的多部分命令非常有效

编辑:在单个调用中添加有关为什么要填充的信息

虽然你不想太在意减少通话,但这是有正当理由的

我曾经被限制在大型机上使用糟糕的ODBC驱动程序,每次调用都会有1.2秒的开销!我是认真的。有时,我会在数据库调用中塞进一点额外的内容。不漂亮。 您还可能会发现,您必须在某个地方配置sql查询,并且不能只调用3个:必须是一个。不应该是这样的,糟糕的设计,但确实如此。你做你该做的! 当然,有时在存储过程中封装多个步骤是非常好的。通常不是为了保存往返,而是为了更紧密的事务,获取新记录的ID,限制权限,提供封装等等。
建立临时表?将所有结果插入临时表,然后从@temp table中选择*

如:

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

等等。。。只有一次访问数据库,尽管我不确定它是否真的更有效

一次往返比三次往返更有效。问题是这是否值得费心。整个ADO.Net和C 3.5工具集和框架都反对您尝试做的事情。TableAdapters、Linq2SQL、EF,所有这些都喜欢处理简单的一次调用==一个结果集语义。因此,您可能会因为试图使框架屈服而失去一些重要的生产力

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


但是,如果你的查询真的是你发布的,即选择所有用户、所有团队和所有权限,那么在减少往返之前,你显然有更重要的事情要做。。。首先,减少结果集。

首先,3次往返其实没什么大不了的。如果你说的是300次往返,那就另当别论了,但对于3次往返,我认为这肯定是一个过早优化的例子

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

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
然后,您可以像直接执行多个行集一样遍历返回的结果集。

I此链接可能会有所帮助


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

单程往返是最重要的考虑因素。这些都是我自己编造的。+1告诉我不要麻烦。相信我,在我开始这么做之前,我会做很多其他的事情,因为web服务器和数据库服务器彼此非常接近。但是我认为MSTF应该实现一些对象。也许ObjectContext中应该有一个IDisposable属性,当输入时,它将一次执行所有累积的查询,将每个reslultset设置为强类型。这将进行4次往返+1是一个很好的代码示例。这就是我在问题中所说的,在一个命令中包含多个sql语句。为此,我一直在寻找处理连接和命令的正确方法:如果这是ASP.Net,并且DB服务器就在Web服务器旁边,或者它只是一个内部应用程序,那么这很可能是一个过早的优化。@Earlz,要么是过早的优化,要么是修复f
或者其他一些设计问题。每次我回来阅读这个问题时,我都很高兴有这么多人阅读我为这个问题编写的简单示例,并假设他们比我更了解我的应用程序的性能特征。请阅读我在下面的回答:连接池几乎总是确保你只打开一个物理连接,因此通常不需要担心打开多个连接的性能成本。