Question

For unit testing purposes I am attempting to call the DBMS_OUTPUT.PUT_LINE procedure from c# using parameters that are bound by name. Since this DBMS_OUTPUT package seems to be a standard on Oracle databases, I am using it to test the code that I have written.

I have been able to successfully call DBMS_OUTPUT.ENABLE with the OraleCommand.BindByName flag set to true. However, that is being called without passing any parameters. I have also been able to call a stored procedure that I made myself by passing a reference cursor bound by name.

When I attempt to call DBMS_OUTPUT.PUT_LINE in a similar fashion I get the following message:

Error Details

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

I am specifying the bind name for the parameter as item according to how the procedure is defined in the 10g documentation for DBMS_OUTPUT. The parameter type for item is defined as VARCHAR2 and that is the type that is being passed to the procedure. When I set the OracleCommand.BindByName flag to false, I am able to call DBMS_OUTPUT.PUT_LINE with no problems.

Here is the code that I am using to run the query:

public bool ExecuteQuery(string procedureName, string[,] queryParameters, bool useReferenceCursor = false)
{
    bool returnStatus = false;

    if (ConnectionStatus() == false)
    {
        //message database connection was interrupted
        return false;
    }

    OracleCommand cmd = new OracleCommand();
    cmd.CommandText = procedureName;
    cmd.CommandType = CommandType.StoredProcedure;
    cmd.BindByName = true;

    cmd.Connection = databaseConnection;

    if (useReferenceCursor)
    {
        cmd.Parameters.Add("output_reference_cursor", OracleDbType.RefCursor).Direction = ParameterDirection.Output;
    }

    for (int parameterSet = 0; parameterSet < queryParameters.GetLength(0); parameterSet++)
    {
        cmd.Parameters.Add(
            queryParameters[parameterSet, 0],
            OracleDbType.Varchar2,
            256,
            queryParameters[parameterSet, 1],
            ParameterDirection.Input
        );
    }

    if (ConnectionStatus() == false)
    {
        //message database connection was interrupted
        return false;
    }

    try
    {
        queryDataReader = cmd.ExecuteReader();
        queryHasRows = queryDataReader.HasRows;
        returnStatus = true;
    }
    catch (Oracle.DataAccess.Client.OracleException error)
    {
        switch (error.Number)
        {
            case 6550:
                Console.WriteLine("The stored procedure specified doesn't exist.");
                DatabaseErrorMessage("The stored procedure doesn't exist. Make sure that the procedure has been properly compiled and that the names match.");
                break;
            default:
                throw error;
        }
        Console.WriteLine(error.ToString());
        queryHasRows = false;
        returnStatus = false;
    }

    return returnStatus;
}

Just for reference, we have decided to pass all parameters to the procedures that we write as OracleDbType.Varchar2 and perform the type casting in the stored procedures that we define. The only exception to this would be reference cursors. I am also using Oracle's ODP.net for access since the Microsoft equivalent is obsolete.

Any feedback or suggestions would be greatly appreciated.

Was it helpful?

Solution

I did a little bit more research and found the answer to the problem.

Even though the first parameter for DBMS_OUTPUT.PUT_LINE is listed as item in the 10g documentation for DBMS_OUTPUT. The actual name for the parameter is A. You need to bind the name using DBMS_OUTPUT.PUT_LINE(A => 'random text').

The actual parameter names for stored procedures can be discovered using the following query:

SELECT 
    argument_name, 
    in_out, 
    data_type 
FROM 
    all_arguments 
WHERE 
    owner = 'SYS' --owner for said procedure
    AND package_name = 'DBMS_OUTPUT' --if procedure is in a package that name, null otherwise
    AND object_name = 'PUT_LINE' --procedure name

The values SYS, DBMS_OUTPUT, and PUT_LINE can be replaced with the values of the the stored procedure that you would like to look up.

Licensed under: CC-BY-SA with attribution
Not affiliated with dba.stackexchange
scroll top