31

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

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

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

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

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

4

6 回答 6

38

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

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

    }
}
于 2010-02-25T18:01:29.857 回答
9

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

编辑:添加有关为什么塞进一个电话的信息。

尽管您不想太在意减少通话次数,但这可能是有正当理由的。

  • 我曾经仅限于针对大型机使用糟糕的 ODBC 驱动程序,每次调用都有 1.2 秒的开销!我是认真的。有时我在我的数据库调用中塞进了一些额外的东西。不漂亮。
  • 您还可能会发现自己必须在某处配置 sql 查询,而且您不能只进行 3 次调用:它必须是一个。不应该那样,糟糕的设计,但它是。你做你该做的!
  • 当然,有时将多个步骤封装在一个存储过程中会非常好。通常不是为了节省往返行程,而是为了更紧密的交易、获取新记录的 ID、限制权限、提供封装等等。
于 2010-02-25T18:04:08.463 回答
2

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

我想说,除非您有一些认真的测量结果表明您需要减少往返次数,否则请弃权。如果您最终确实需要这个,那么使用存储过程至少提供一种 API 语义。

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

于 2010-02-25T18:06:14.340 回答
1

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

考虑使用至少相同的连接打开;根据这里所说的,打开连接几乎是 Entity-Framework 中性能成本的最高领导者。

于 2010-11-30T12:12:26.207 回答
0

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

如,

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

等等......只有一次访问数据库,虽然我不确定它实际上是否更有效。

于 2010-02-25T18:05:56.587 回答
0

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

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

于 2010-02-25T18:11:44.853 回答