Search code examples
c#oracleado.netoracle18csystem.data.oracleclient

OracleCommandBuilder.DeriveParameters() throws OracleException: ORA-06564: object does not exist ORA-06512: at "SYS.DBMS_UTILITY"


Using the OracleClient that comes with ADO.NET in .NET Framework, I'm trying to call OracleCommandBuilder.DeriveParameters() method on a procedure in the database, but I keep getting an OracleException with the message: ORA-06564: object CustOrdersOrders does not exist, even though I created the procedure successfully. I'm more familiar with SQL Server, so perhaps I'm missing something here.

SQL

file 1.sql:

create or replace PACKAGE PKGENTLIB_ARCHITECTURE
IS
TYPE CURENTLIB_ARCHITECTURE IS REF CURSOR;
END PKGENTLIB_ARCHITECTURE;
/

file 2.prc:

CREATE OR REPLACE PROCEDURE "CustOrdersOrders"(VCUSTOMERID IN Orders.CustomerID%TYPE := 1, CUR_OUT OUT PKGENTLIB_ARCHITECTURE.CURENTLIB_ARCHITECTURE)
    AS

BEGIN
    OPEN cur_OUT FOR
    SELECT
        OrderID,
        OrderDate,
        RequiredDate,
        ShippedDate
    FROM Orders
    WHERE CustomerID = vCustomerId;
END;
/

file 3.prc

CREATE OR REPLACE PROCEDURE ADDCOUNTRY
(vCountryCode IN Country.CountryCode%TYPE,
 vCountryName IN Country.CountryName%TYPE
)
AS
BEGIN
    INSERT INTO Country (CountryCode,CountryName)
    VALUES (vCountryCode,vCountryName);
END;
/

All of these files were executed in SQL*Plus as @"path\to\file1.sql".

App.config

<configuration>
  <connectionStrings>
    <add name="OracleTest" connectionString="Data Source=(DESCRIPTION=(CID=xe)(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)(HOST=localhost)(PORT=1521)))(CONNECT_DATA=(SID=xe)(SERVER=DEDICATED)));User Id=SYSTEM;Password=oracle;" providerName="System.Data.OracleClient" />
  </connectionStrings>
</configuration>

Code

private DbConnection connection;
private OracleCommand command;

[TestInitialize]
public void Initialize()
{
    String connectionString = ConfigurationManager.ConnectionStrings["OracleTest"].ConnectionString;
    connection = new OracleConnection(connectionString);
    command = connection.CreateCommand() as OracleCommand;
    command.CommandType = CommandType.StoredProcedure;
    connection.Open();
}

[TestMethod]
public void DeriveParametersWithoutUserDefinedTypes()
{            
    command.CommandText = "AddCountry";
    OracleCommandBuilder.DeriveParameters(command);
    Assert.AreEqual(2, command.Parameters.Count); // fails because Count = 0
}

[TestMethod]
public void DeriveParametersWithUserDefinedTypes()
{
    command.CommandText = "CustOrdersOrders";
    OracleCommandBuilder.DeriveParameters(command); //throws 'ORA-06564: object CustOrdersOrders does not exist\nORA-06512: at "SYS.DBMS_UTILITY", line 156\nORA-06512: at line 1'
    Assert.AreEqual(2, command.Parameters.Count);
}

[TestCleanup]
public void Cleanup()
{
    connection?.Dispose();
}

More Details

This is happening in a fork I made for the Enterprise Library Data Access Application Block here in an attempt to revive this library. That's why it's using the System.Data.OracleClient and not the ODP.NET.

The tests are running on an Oracle Database XE I installed locally.


Solution

  • From my Oracle-ish point of view, this was your huge mistake:

    CREATE OR REPLACE PROCEDURE "CustOrdersOrders"
                                -                -
                                these double quotes
    

    Because, by default Oracle stores all object names into the dictionary in upper case, but you can reference it any way you want, e.g. custordersorders, CUSTordERsordERS, CUSTORDERSORDERS, CustOrdersOrders - no problem. But, if you enclose any name (procedure, table, column, ...) into double quotes, you must use double quotes any time you reference that object, enclosed into same double quotes and matching letter case exactly as you used it when creating that object.

    So: either recreate the procedure as CREATE OR REPLACE PROCEDURE CustOrdersOrders (which is what I'd suggest), or use double quotes.