2

我有几个长时间运行的 Sybase 存储过程,它们带有输出进度消息的打印语句。我们一直使用 isql 或通过 aseisql 或 sqladvantage(所有 sybase 特定工具)手动执行这些 SP。这些工具在 SP 输出后立即正确显示打印消息,因为 SP 都包含“set flushmessage on”。

我编写了一个 C# 控制台包装应用程序,它通常执行一个过程并转换结果。然而令人沮丧的是,我无法捕获打印消息并将它们写入标准输出。这似乎应该是微不足道的,我很惊讶我不能在互联网上出现太多。

我正在使用 ODBC 连接并将必要的事件处理程序添加到 InfoMessage 回调挂钩。在我的测试中,这是通过 print 语句消息调用的——但不是实时的,因为它们是发布的。在将结果集发送回客户端之前,它似乎不会被调用,然后只对所有消息调用一次。我尝试使用 DataAdapter 填充 DataSet,使用 ExecuteNonQuery、ExecuteReader 等,但它似乎并没有改变行为。我还尝试了 Sybase System 11 和 Adaptive Server Enterprise ODBC 驱动程序,没有任何区别。

所以我的问题是双重的:

1)首先我想确切地了解这里发生了什么 - 我知道存储过程会立即将消息发送到数据库服务器,但它显然被缓存在某处 - 要么不是由 ODBC 驱动程序从服务器读取,要么读取并缓存在驱动程序内存本身?- 通常我只是想到我的应用程序中的调用线程阻塞了数据库调用,但试图思考到底发生了什么我猜线程在驱动程序代码轮询结果/消息中很忙,我不知道那是怎么回事与回调函数一起工作以及何时处理。在我的应用程序中进行调试似乎就在我获得控制权以处理结果之前被调用。

2)其次,我真正想知道的是是否有任何方法可以改变行为,以便将消息立即发送回客户端。

任何帮助将不胜感激,但请不要提出“你为什么不以 XYZ 方式做事”的建议,因为我真的在寻求解决和理解这个问题的具体帮助 - 如果问题被证明是,我可以想到许多替代方案不可逾越。

这里有一个小测试台来说明代码:

存储过程:

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

.NET 代码片段:

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(@"<connection string here>"))
        {
            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);
        }
    }
}
}
4

1 回答 1

0

尝试RAISERROR(...) WITH NOWAIT代替 PRINT

于 2013-12-12T10:55:51.240 回答