title: DB connection InfoMessage callback not firing immediately for stored proc print statements
body: <p>I have several long running Sybase stored procedures with print statements that output progress messages. We've always executed these SPs using isql or manually through aseisql or sqladvantage (all sybase specific tools). These tools correctly display the print messages as soon as they are output by the SP as the SPs all contain "set flushmessage on". </p>
  
  <p>I've written a C# console wrapper app which generically executes a procedure and transforms the results. However frustratingly I have been unable to capture the print messages and write them out to std out. This seems like it should be trivial and I'm amazed I cant turn up much on it on the internet.</p>
  
  <p>I'm using an ODBC connection and am adding the necessary event handler to the InfoMessage callback hook. In my testing, this is getting called with the print statement messages - <em>however not in realtime as they are issued</em>. It doesn't seem to get called until a resultset is sent back to the client, then it is called once only with all messages. I've tried using a DataAdapter to fill a DataSet, using ExecuteNonQuery, ExecuteReader and so on and it doesn't seem to change the behaviour. I've also tried both the Sybase System 11 and Adaptive Server Enterprise ODBC drivers and no difference.</p>
  
  <p>So my question is twofold:</p>
  
  <p>1) firstly I'd like to understand exactly what is occuring here - I know the stored procedure is immediately sending the message to the database server but it's obviously being cached somewhere - either not read off the server by the ODBC driver or read and cached in the driver memory itself? - Normally I just think of the calling thread in my app blocking on a database call, but trying to think through what's really going on I guess the thread is busy within the driver code polling for results/messages and I don't know how that kind of works in with the callback function and when that is processed. Debugging in my app it seems to be called just before I get control back to process results.</p>
  
  <p>2) Secondly, what I'd really like to know is whether there is any way to change the behaviour so the messages are sent back to the client immediately.</p>
  
  <p>Any help would be greatly appreciated, but please refrain from "why don't you do things XYZ way instead" suggestions as I'm really after specific help solving and understanding this problem -I can think of many alternatives should the issue prove to be insurmountable.</p>
  
  <p>Here's a little test-rig to illutsrate the code:</p>
  
  <p>Stored proc:</p>
  
  <pre><code>create procedure sp_test
  as
  begin
      set flushmessage on
  
      print "Step 1"
  
      waitfor delay "00:00:10"
  
      print "Step 2"
  
      waitfor delay "00:00:10"
  
      select 10 as "number"  -- preferably put some sort of select from a table here
  
      print "Final Step"
  
  end
  go
  grant execute on sp_test to public
  go
  </code></pre>
  
  <p>.NET Code snippet:</p>
  
  <pre><code>using System.Collections.Generic;
  using System.Data;
  using System.Data.Odbc;
  using System.Data.SqlClient;
  using System.Linq;
  using System.Text;
  
  namespace ConsoleApplication1
  {
  class Program
  {
      static void Main(string[] args)
      {
          using (var conn = new OdbcConnection(@"&lt;connection string here&gt;"))
          {
              conn.InfoMessage += OnInfoMessage;
              conn.Open();
              var command = new OdbcCommand("sp_test", conn);
              command.Timeout = 50000;  // i added this later syntax might be wrong
              var ds = new DataSet();
              var da = new OdbcDataAdapter(command);
              da.Fill(ds);
              Console.ReadKey();
          }
      }
  
      private static void OnInfoMessage(Object sender, OdbcInfoMessageEventArgs args)
      {
          foreach (OdbcError error in args.Errors)
          {
              Console.WriteLine(error.Message);
          }
      }
  }
  }
  </code></pre>