我正在将一个应用程序从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"命令已经在进行中:从表A中选择* 那么有什么方法可以做到这一点而不必为每个命令建立连接呢?
问题是,当您在第一个命令/读取器的上下文中时,会为此建立连接。在从第一个命令/读取器释放连接之前,无法运行第二个命令,依此类推。
解决方案是将要获取的数据加载到列表中,然后按该列表进行迭代并运行第二个命令/读取器。在第二个命令/读取器上,您还可以将结果加载到另一个列表中,并对其进行迭代。
最后,我的建议是让您评估您想要从数据库中获得的数据以及您正在执行的查询。您的想法是正确的,但它会增加数据库的巨大过载,这将在尝试从同一表中获取数据的其他并发用户中产生问题。
为了补充@paulo-correia的上述响应,打开第二个连接可能很好,具体取决于您的用例。假设您使用的是池化并且您不缺少连接(即大规模并发场景(,这样做并没有错,它将节省缓冲第一个查询结果所需的客户端内存。但是,请注意,如果两个查询需要在事务中,则这是不可能的。