Oracle自定义Web界面(ASP.NET,C#) - 获取DBMS_OUTPUT内容

时间:2015-09-15 01:10:49

标签: c# asp.net oracle

我正在为Oracle DB编写一个定制的简单Web界面,使用ASP.NET,C#中的Web API项目和Oracle.DataAccess(ODP.NET)。这是一个教育项目,我正在设计一个大学课程的额外项目。我设计这个项目有几个原因,但结果是使用Oracle提供的工具(SQL Developer,Enterprise Manage Express等)不适合手头的任务。

我有一个API调用,可以接受查询字符串,对DBMS执行它,并将DBMS的输出作为JSON数据返回,以及一些额外的返回数据。这对于简单的SELECT查询和其他基本DDL / DML查询已经足够了。但是,现在我们正在分支到PL / SQL。

例如,我们执行的最基本的PL / SQL HELLO WORLD程序如下:

BEGIN
    DBMS_OUTPUT.PUT_LINE('Hello World');
END;

当我将此查询提供给我的C#API时,它确实成功执行。但是,我希望能够检索DBMS_OUTPUT.PUT_LINE调用的输出。

之前已经解决了这个问题,我已经研究了一些解决方案,并介绍了一个涉及在数据库上调用以下PL / SQL的代码:

BEGIN 
    Dbms_output.get_line(:line, :status);
END;

C#代码显然会在发送之前为请求创建并添加正确的参数对象。我打算重复调用此函数,直到NULL值返回,表示输出结束。然后将此数据添加到API返回的JSON对象中,以便Web界面可以显示输出。但是,此函数永远不会返回任何输出行。

我的预感(我自己还在学习Oracle,所以不确定)是服务器实际上没有输出数据,还是在PL / SQL匿名过程(Hello World)程序之后刷新了缓冲区饰面。

还建议将set serveroutput on;添加到PL / SQL查询中,但这不起作用:它产生错误ORA-00922: missing or invalid option

以下是用于从DBMS_OUTPUT缓冲区检索输出行的实际C#代码:

private string GetDbmsOutputLine(OracleConnection conn)
{
    OracleCommand command = new OracleCommand
    {
        CommandText = "begin dbms_output.get_line(:line, :status); end;",
        CommandType = CommandType.Text,
        Connection = conn,
    };

    OracleParameter lineParameter = new OracleParameter("line",
        OracleDbType.Varchar2);
    lineParameter.Size = 32000;
    lineParameter.Direction = ParameterDirection.Output;
    command.Parameters.Add(lineParameter);

    OracleParameter statusParameter = new OracleParameter("status",
        OracleDbType.Int32);
    statusParameter.Direction = ParameterDirection.Output;
    command.Parameters.Add(statusParameter);

    command.ExecuteNonQuery();

    if (command.Parameters["line"].Value is DBNull)
        return null;

    string line = command.Parameters["line"].Value as string;

    return line;
}

编辑:我尝试在执行用户代码之前手动调用以下过程:BEGIN DBMS_OUTPUT.ENABLE(32768); END;。这样执行时没有错误,但在执行此操作后,稍后对DBMS_OUTPUT.GET_LINE的调用仍然返回null。

看起来可能发生的事情是,每次我对数据库执行新查询时,即使它位于同一连接上,也要清除DBMS_OUTPUT缓冲区。我不确定是否是这种情况,但它似乎是 - 没有其他任何东西可以解释缓冲区中缺少数据。

仍在寻找处理此问题的方法......

要记住的要点:

  • 这是一个学生培训和发展的学术项目;因此,预计这种迷你应用程序不会以任何方式“生产就绪”。允许用户执行通过Web发布的原始查询显然会导致各种安全风险 - 这就是为什么永远不会将其放入实际的生产场景中。
  • 我目前打开一个连接,并通过将其传递到我创建的每个OracleCommand对象中来维护它。从理论上讲,这应该意味着保持缓冲区,但似乎并非如此。我写的数据首先没有进入缓冲区,或者每当实际对数据库连接执行OracleCommand对象时刷新缓冲区。

1 个答案:

答案 0 :(得分:0)

有一点需要注意,实际上你永远不会编写代码,希望任何人都能看到你试图写入SELECT * FROM data_blocks WHERE MATCH(tags) AGAINST("+[16]"); 的数据...

在会话中,您需要调用enter image description here来分配dbms_output写入的缓冲区。根据Oracle版本,您可以传入dbms_output以指示您需要无限制的缓冲区大小。在旧版本中,您需要分配固定的缓冲区大小(如果您尝试向缓冲区写入太多数据,则会收到错误)。然后,您将调用调用null的过程。最后,您可以致电dbms_output.put[_line]。请注意,所有这三件事都必须在单个会话的上下文中发生。每个会话都有一个单独的dbms_output.get[_line]缓冲区(或没有dbms_output缓冲区)。