I'm surprised the driver doesn't provide a way to do this-- but you could manually execute the SQL statements to declare a cursor, open it and fetch from it in batches. i.e. (and this code is very dubious as I'm not a C# guy):
new PgsqlCommand("DECLARE cur_data NO SCROLL CURSOR AS "
+ strQuery, _conn).ExecuteNonQuery();
do {
NpgsqlDataReader reader = new NpgsqlCommand("FETCH 100 FROM cur_data", _conn)
.ExecuteReader();
int rows = 0;
// read data from reader, incrementing "rows" for each row
} while (rows > 0);
new PgsqlCommand("CLOSE cur_data", _conn).ExecuteNonQuery();
Note that:
- You need to be inside a transaction block to use a cursor, unless you specify the "HOLD" option when declaring it, in which case the server will spool the results to a server-side temp file (you just won't have to transfer it all at once though)
- The
cursor_tuple_fraction
setting may cause a different plan to be used when executing a query via a cursor as opposed to in immediate mode. You may want to do "SET cursor_tuple_fraction=1" just before declaring the cursor since you're actually intending to fetch all the cursor's output.