views:

271

answers:

2

Hi.

I have a large table (2,000,000 rows) and I'd like to print each record to the screen, one at time, without loading the entire table into memory.

//pseudo code
var cmd = new NpgSQLCommand();
cmd.CommandText = "SELECT * FROM mytable;"
IReader reader = cmd.ExecuteReader(); //blocks until the entire set is returned

while(reader.Read()) //ideally each call to read loads more results from the db.
{
// print record name

}

So as noted in the code above, the ExecuteReader() doesn't continue until the entire set is loaded into memory. How do I change this behavior so the results are streamed?

Thanks

ETA: While this seems like homework, it's not. It's just an easier way to describe a problem that involves reading an entire table with a single query but processing the results a row at a time.

ETA x2:

From npgsql Warning: There is a known issue when calling ExecuteReader and large tables. Currently Version 1 of Npgsql gets all data from table before returning. If you are experiencing bad performance in such cases, you may need to use a server cursor to page through rows. For that, you can use a code like the following:

A: 

Okay, well it looks like this is a known issue with npgsql 1.0:

The workaround is to use a server cursor:

using System;
using System.Data;
using Npgsql;

public static class NpgsqlUserManual
{
  public static void Main(String[] args)
  {
    NpgsqlConnection conn = new NpgsqlConnection("Server=127.0.0.1;Port=5432;User Id=joe;Password=secret;Database=joedata;");
    conn.Open();

    NpgsqlCommand command = new NpgsqlCommand("select version()", conn);
    String serverversion;

    try
    {
      serverversion = (String)command.ExecuteScalar();
      Console.WriteLine("PostgreSQL server version: {0}", serverversion);
    }


    finally
    {
      conn.Close();
    }
  }
}
Alan
It's not a known issue with Postgres, it's a known - and fixed - issue with Npgsql. In the case of the original querant this is the answer to go for as they don't want to move from Npgsql1, but anyone coming across this in a search who has the same problem should note that it hasn't held for Npgsql2.0 (except with a certain backwards-compatibility feature set) for some time, and upgrading should give better performance than a server cursor.
Jon Hanna
You're right Jon. It *was* a known issue, and is *still* an issue with Npgsql 1.0.
Alan
+1  A: 

Hi!

Npgsql2 now handles large resultsets much better. It doesn't load all data to memory. So, you don't need to use a server side cursor anymore.

I hope it helps.

Francisco Figueiredo Jr. Npgsql Lead Developer

Francisco
Thanks. We've invested quite a bit of code with NPGSQL v1, so moving to v2 would be at a significant cost/risk. Are there documents outlining the upgrade process from v1 to v2? I was able to compile against the latest version of npgsql, but there were db connection timeouts when I ran my executable.
Alan
Hi. Sorry for late response.... We don't have any document talking about upgrade process. I think we should provide one :)We had some problems with command/connection timeouts. I just finished committing a fix for the last one, I hope. Please, try the latest version and see if it works ok. Mostly of the time, the biggest problem people have moving from v1 to v2 is exactly this different behavior of Npgsql regarding resultsets returns. Today Npgsql doesn't allow multiple resultsets open at the same time. In order to revert back, you can use the Preload Reader connection string to true.
Francisco