【问题标题】:Call Oracle procedure from C# when procedure is in different schema当过程处于不同模式时,从 C# 调用 Oracle 过程
【发布时间】:2020-01-08 22:27:44
【问题描述】:

我正在尝试调用一个非常简单的过程,如果我在 Toad 编辑器中,它可以正常工作:

BEGIN OtherSchema.P_CloseBatch('BatchName'); END;

此架构有权执行存在于 OtherSchema 中的 P_CloseBatch。

我在 C# 中使用以下代码连接到相同的架构:

try 
{ 
    using (OracleConnection connection = new OracleConnection(oracleStgConnectionString))
    {
          connection.Open();
          OracleCommand command = new OracleCommand();
          command.Connection = connection;
          command.CommandType = CommandType.StoredProcedure;
          command.CommandText = "BEGIN OtherSchema.P_CloseBatch('BatchName'); END;";
          command.ExecuteNonQuery();
          connection.Close();
     }
}
catch (Exception e)
{
     Log.Info(e.Message);
}

当我到达 command.ExecuteNonQuery 时,它给了我一个很长的错误:

{"ORA-06550: line 1, column 83:\nPLS-00103: Encountered the symbol \")\" when期待以下之一:\n\n ( - + case mod new not null \n \ n continue avg count current exists max min prior sql stddev\n sum variance execute forall merge time timestamp interval\n date \n pipe\n \n

我的所有搜索都表明 CommandText 是合适的,但事实并非如此。我能想到的只是它在不同的模式中。是这个问题,还是我没有看到其他问题?

如果不是上面的 CommandText 值,而是使用以下值:

command.CommandText = "OtherSchema.P_CloseBatch('BatchName')";

那么我得到的错误是:

  • $exception {"ORA-06550:第 1 行,第 7 列:\nPLS-00801:内部错误 [22503]\nORA-06550:第 1 行,第 7 列:\nPL/SQL:语句被忽略"} Oracle.ManagedDataAccess .Client.OracleException

我可以把它拆分,这样命令文本是分开的,批处理名称作为参数添加:

 connection.Open();
 OracleCommand command = new OracleCommand();
 command.Connection = connection;
 command.CommandType = CommandType.StoredProcedure;
 command.CommandText = "OtherSchema.P_CloseBatch(:batchname)";
 String parameterBatchName = "BatchName";
 command.Parameters.Add(new OracleParameter(":batchname", parameterBatchName ));
 command.ExecuteNonQuery();
 connection.Close();

那个错误是 "+ $exception {"ORA-01008: not all variables bound"} Oracle.ManagedDataAccess.Client.OracleException "

这似乎是一个非常简单的错误。我使用与确实有效的查询相同的语法,但它们是更新而不是对过程的调用。

【问题讨论】:

  • 当您指定CommandType.StoredProcedure 时,CommandText 应该是过程的名称,而不是 PL/SQL 脚本。然后添加"BatchName" 值作为参数。
  • @madreflection - 这也给出了一个错误,但是一个不同的错误。
  • 那是因为您指定的不仅仅是名称。
  • @madreflection - 好的,我会尝试添加参数。不挂断。 (因为我已经尝试过了,但也遇到了错误,但可能是语法问题,再试一次就可以了。)
  • @madreflection - 仍然不行。然而,这似乎是一个简单的错误。

标签: c# oracle


【解决方案1】:

当您指定CommandType.StoredProcedure 时,CommandText 应该是过程的名称,而不是 PL/SQL 脚本。参数在Parameters 集合中传递。

using (OracleConnection connection = new OracleConnection(oracleStgConnectionString))
using (OracleCommand command = connection.CreateCommand())
{
    connection.Open();

    command.BindByName = true;
    command.CommandType = CommandType.StoredProcedure;
    command.CommandText = "OtherSchema.P_CloseBatch";

    command.Parameters.Add(new OracleParameter()
    {
        ParameterName = "batchname",
        OracleDbType = OracleDbType.NVarchar2
        Value = parameterBatchName
    });

    command.ExecuteNonQuery();

    // Call to connection.Close removed as the "using" block already does that.
}

我还进行了一些其他更改:

  • 使用connection.CreateCommand 创建command,因为它在返回对象之前分配了连接。

  • using 阻止 command,因为它也是一次性的。

  • 设置BindByName,所以我指定的参数名称实际上意味着什么。

【讨论】:

  • 我终于明白了你所说的我使用的不仅仅是名字的意思。有用!非常感谢。
  • 不客气。您能否整合我所做的其他更改/建议?
  • 是的——我都用过。由于我混淆了我的代码,我不得不做一个小改动。你帮了很多忙,我现在正在测试我的最后一部分,该代码在 5 个地方(针对 5 个不同的批次)。
  • 你也可以使用更短的形式command.Parameters.Add("batchname", OracleDbType.Varchar2).Value = parameterBatchName;
  • 确实可以,但是我不建议这样做。我已经看到错误使用错误重载的 SO 问题,例如使用错误的 Db Type 枚举,它最终成为 value 参数。这种方式可以防止任何这些错误。另外,您不必考虑所需重载的参数顺序。无论您需要设置哪些属性,例如包括方向;这种方式使其完全统一。
猜你喜欢
  • 2015-01-20
  • 1970-01-01
  • 2014-03-16
  • 2011-04-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-08-12
相关资源
最近更新 更多