Npgsql:一个连接上的嵌套SQL命令

时间:2019-05-29 09:21:15

标签: c# postgresql npgsql

我正在将应用程序从firebird移植到postgres,并且有一堆嵌套的sql命令。第一个命令是第二个命令运行所必需的,有些函数具有5或6个嵌套命令,并且它们都使用相同的连接。我只是想知道是否有一种方法可以在一个连接上完成所有这些操作而不必重写整个过程。

    static void NestedCommandsOnOneConnection()
    {
        using (NpgsqlConnection connection = new NpgsqlConnection(ConnectionString))
        {
            using (NpgsqlCommand command = new NpgsqlCommand("SELECT * FROM tableA", connection))
            {
                using (NpgsqlDataReader reader = command.ExecuteReader())
                {
                    using (NpgsqlCommand command2 = new NpgsqlCommand("SELECT * FROM tableB where column1 = @column1", connection))
                    {
                        command2.Parameters.AddWithValue("@column1", reader["column1"]);

                        using (NpgsqlDataReader reader2 = command2.ExecuteReader())
                        {
                            while (reader2.Read())
                            {
                                //Do things
                            }
                        }
                    }
                }
            }
        }
    }

//编辑:如果我做这样的事情会更好吗?

    static void NestedCommandsOnOneConnection()
    {
        using (NpgsqlConnection connection = new NpgsqlConnection(ConnectionString))
        {
            var column1 = "";
            using (NpgsqlCommand command = new NpgsqlCommand("SELECT * FROM tableA LIMIT 1", connection))
            {
                using (NpgsqlDataReader reader = command.ExecuteReader())
                {
                    while(reader.Read())
                    {
                       column1 = reader["column1"].ToString();
                    }

                }
            }
            using (NpgsqlCommand command2 = new NpgsqlCommand("SELECT * FROM tableB where column1 = @column1", connection))
            {
                command2.Parameters.AddWithValue("@column1", column1);

                using (NpgsqlDataReader reader2 = command2.ExecuteReader())
                {
                    while (reader2.Read())
                    {
                        //Do things
                    }
                }
            }
        }
    }

执行第二个命令时,出现错误消息msg“一个命令已在执行中:SELECT * FROM tableA”那么有没有办法做到这一点而不必为每个命令建立连接?

2 个答案:

答案 0 :(得分:1)

问题是当您在第一个命令/阅读器上的上下文中时,将为此建立连接。在您从第一个命令/阅读器释放连接之前,您将无法运行第二个命令,依此类推。

解决方案是将要获取的数据加载到列表中,并对该列表进行迭代并运行第二个命令/阅读器。在第二个命令/阅读器上,您还将结果加载到另一个列表中,并对其进行迭代。

最后,我的建议是让您评估要从数据库中获取的数据以及正在执行的查询。您的想法是正确的,但是它在数据库上增加了巨大的负担,这将在试图从同一表中获取数据的其他并发用户中产生问题。

答案 1 :(得分:0)

要添加到上述@ paulo-correia的响应中,根据您的用例,打开第二个连接可能很好。假设您正在使用缓冲池并且不缺乏连接(即大规模并发方案),那么这样做没有错,它将节省用于缓冲第一个查询结果的客户端内存。但是,请注意,如果两个查询需要在事务中进行,则不可能。