c# - 数据库连接 InfoMessage 回调不会立即触发存储过程打印语句

标签 c# stored-procedures odbc sap-ase

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

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

我正在使用 ODBC 连接并将必要的事件处理程序添加到 InfoMessage 回调 Hook 。在我的测试中,这是通过打印语句消息调用的 - 但是在它们发出时不是实时的。在将结果集发送回客户端之前,它似乎不会被调用,然后它只对所有消息调用一次。我试过使用 DataAdapter 填充数据集,使用 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);
        }
    }
}
}

最佳答案

尝试使用 RAISERROR(...) WITH NOWAIT 而不是 PRINT

关于c# - 数据库连接 InfoMessage 回调不会立即触发存储过程打印语句,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12071390/

相关文章:

c# - 如何正确暂停/停止线程?

sql - 从存储过程返回游标

mysql - shell脚本中mysql存储过程的关联数组

python - 如何在python中读取sql server View ?

java - 如何在整个应用程序中使用一个数据库连接对象?

hadoop - HIVE ODBC - 故障转移

c# - Sitecore 8 MVC ajax调用路由寄存器

C# 控制台应用程序 - 佣金计算器 - 如何将变量传递到 Main()

c# - Windows 应用商店应用程序中带密码的 ZipArchive

java - 发送 POST 到 HTTPS - 逻辑问题