从C#和ODP.NET调用包中的函数的代码

时间:2013-09-13 14:13:05

标签: c# oracle odp.net

我尝试用ODP.NET编写C#代码来调用包中的函数。我收到以下两个错误:

ORA-06550: line 1, column 7:
PLS-00306: wrong number or types of arguments in call to INSERT_FUNC'
ORA-06550: line 1, column 7:
PL/SQL: Statement ignored

ORA-06550: line 1, column 7:
PLS-00221: 'INSERT_FUNC' is not a procedure or is undefined
ORA-06550: line 1, column 7:
PL/SQL: Statement ignored

我的OracleCommand设置为:

cmd.CommandText = "PKG_NAME.INSERT_FUNC";
cmd.CommandType = CommandType.StoredProcedure;
  1. 我应该如何将参数传递给下面的函数?
  2. 我是否需要添加ReturnValue参数?我见过很多论坛都在讨论是否需要在ReturnValue对象上添加OracleParameter参数作为第一个OracleCommand
  3. 我很感激任何建议。

    CREATE OR REPLACE
    PACKAGE BODY pkg_name IS
      FUNCTION insert_func (
          i_description IN  tableName.description%TYPE,
          i_theme       IN  tableName.theme%TYPE,
          o_id          OUT tableName.id%TYPE,
          o_error_msg   OUT VARCHAR2 )
        RETURN NUMBER
      IS
        l_program VARCHAR2(100) := 'PKG_NAME.INSERT_FUNC';
      BEGIN
        INSERT INTO tablea ( event_id, id, description, theme, lock_version )
          VALUES ( rms12.tablea_seq.NEXTVAL, rms12.tablea_id_seq.NEXTVAL, i_description, i_theme, NULL );
        INSERT INTO tableb ( id, description, theme )
          VALUES ( rms12.id_seq.CURRVAL, i_description, i_theme );
        SELECT rms12.id_seq.CURRVAL
          INTO o_id
          FROM dual;
        RETURN 1;
      EXCEPTION
        WHEN OTHERS THEN
          o_error_msg := sql_lib.create_msg(
              'PACKAGE_ERROR', SQLERRM, l_program, TO_CHAR( SQLCODE ) );
          RETURN 0;
      END insert_func;
    END pkg_name;
    

3 个答案:

答案 0 :(得分:22)

这是我在这个论坛上的第一个问题,我很乐意发表自己的答案。

我们可以通过设置CommandType.StoredProcedure来使用ODP.NET调用oracle包函数。

ORA-06550: line 1, column 7:
PLS-00221: 'INSERT_FUNC' is not a procedure or is undefined
ORA-06550: line 1, column 7: PL/SQL: Statement ignored

如果出现此错误,只需将此行添加为命令对象的第一个参数:

cmd.Parameters.Add("Return_Value", OracleDbType.Int16,
    ParameterDirection.ReturnValue);

以下是工作代码:

using (var conn = new OracleConnection(oradb))
using (var cmd = conn.CreateCommand())
{
    cmd.CommandType = CommandType.StoredProcedure;
    cmd.CommandText = "PKG_NAME.INSERT_FUNC";

    cmd.BindByName = true;

    cmd.Parameters.Add("Return_Value", OracleDbType.Int16,
        ParameterDirection.ReturnValue);
    cmd.Parameters.Add("i_description", OracleDbType.Varchar2, 1000,
        promotionEventSetupDetails.PromotionDescription,
        ParameterDirection.Input);
    cmd.Parameters.Add("i_theme", OracleDbType.Varchar2, 80,
        promotionEventSetupDetails.PromotionTheme,
        ParameterDirection.Input);
    cmd.Parameters.Add("o_id", OracleDbType.Varchar2,
        ParameterDirection.Output);
    cmd.Parameters.Add("o_error_msg", OracleDbType.Varchar2,
        ParameterDirection.Output);

    conn.Open();
    using (var dr = cmd.ExecuteReader())
    {
        // do some work here
    }
}

答案 1 :(得分:1)

对于最新版本的Oracle,这必须是新的。我之前能够使用我的C#代码中的所有输入参数之后列出的返回值参数来执行此操作,但是在12c上执行此操作后,我遇到了这个问题,现在可以使用返回val param的这个建议。

答案 2 :(得分:0)

我创建了一个通用方法,可以帮助您获得函数结果

var result = await 
 dbManager.ExecuteFunctionResultAsync<Oracle.ManagedDataAccess.Types.OracleDecimal>(
                     functionName, parameters.List);


public async Task<T> ExecuteFunctionResultAsync<T>(string spName, IEnumerable<OracleParameter> paramaters)
        {
            using (OracleConnection connection = new OracleConnection(this.connectionString))
            {
                connection.Open();
                using (OracleCommand comm = new OracleCommand(spName, connection))
                {
                    comm.CommandType = CommandType.StoredProcedure;
                    comm.BindByName = true;
                    string returnParam = "return_value";
                    comm.Parameters.Add(new OracleParameter() {
                        ParameterName = returnParam,
                        Direction = ParameterDirection.ReturnValue,
                        OracleDbType = OracleDbType.Int16,
                    });

                    this.SetCommandParameters(comm, paramaters);
                    await comm.ExecuteNonQueryAsync();
                    var result = (T)comm.Parameters[returnParam].Value;

                    return result;
                }
            }
        }

private void SetCommandParameters(OracleCommand command, IEnumerable<OracleParameter> paramaters)
        {
            if (paramaters != null)
            {
                foreach (OracleParameter p in paramaters)
                {
                    command.Parameters.Add(p);
                }
            }
        }