views:

138

answers:

2

How to process SqlCommand result (rows) as they come? In other words, I am trying to do exactly what Sql Management Studio 2005 does when executing a query with many thousand rows. To me, it looks like as soon as Sql has found the first result, it notify the UI and display the rows as they come...

I suppose that it can be done asynchronously with BeginExecuteReader and EndExecuteReader, however (in my tests) the callback method is called only when the result set is completed. Any idea on how to replicate what Sql Management Studio 2005 does?

Thanks!

+3  A: 

Don't do an async operation, but just call ExecuteReader and then iterate over the result set as it comes in.

using(SqlCommand cmd = new SqlCommand(......))
using(SqlDataReader rdr = cmd.ExecuteReader())
{
    while(rdr.Read())
    {
        // read and interpret row
        // possibly update GUI or something
    } 
}

If you need to update some UI or something while processing those, you can always call another method with a new row that's been read.

Marc

marc_s
+1  A: 

For your app to remain responsive, your main GUI thread has to be free to process incoming messages. This is even true for drawing to the screen; you may update a label's text, but it won't be displayed on screen until after the "update label text" windows message has been processed.

The easy way of being responsive is calling Application.DoEvents() frequently. This will basically process all incoming messages and return.

If you have single operations that take a long time, like the ExecuteReader(), you won't be able to call DoEvents() often enough. In that case you have to fall back to a background thread. One relatively easy way to use a background thread is the BackgroundWorker component. There's a nice example in this blog post.

Andomar
I agree, to keep the UI responsive, long running/intensive tasks should be executed from another thread.Application.DoEvents() is easy but dirty.
Guillaume
My question is not about having a responsive UI, I am pretty well aware of those techniques. The question is about asynchronous Sql and processing the data as it come...
Martin
Data doesn't start to arrive before ExecuteReader() finishes. SQL Server sends the first row when you call SqlDataReader.Read(). SSMS probably executes both ExceuteReader and the following Read() calls in a background thread. The background thread periodically tells the GUI thread to add the newly received rows to a list or text control.
Andomar