OracleCommandBuilder.DeriveParameters() 抛出 OracleException: ORA-06564: 对象不存在 ORA-06512: 在 "SYS.DBMS_UTILITY"

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

在 .NET Framework 中使用 ADO.NET 附带的 OracleClient,我试图在数据库中的过程上调用 OracleCommandBuilder.DeriveParameters() 方法,但我不断收到 OracleException消息:ORA-06564: object CustOrdersOrders does not exist,即使我成功创建了过程。我对 SQL 服务器比较熟悉,所以我可能在这里遗漏了一些东西。

SQL

文件1.sql:

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

文件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;
/

文件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;
/

所有这些文件都在 SQL*Plus 中执行为 @"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>

代码

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();
}

更多详情

这发生在我为企业图书馆数据访问应用程序块 here 制作的一个分支中,试图恢复这个图书馆。这就是为什么它使用 System.Data.OracleClient 而不是 ODP.NET.

测试是在我本地安装的 Oracle 数据库 XE 上进行的运行。

从我的 Oracle-ish 观点来看,这是你的大错:

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

因为,默认情况下,Oracle 将所有对象名称以大写形式存储到字典中,但您可以按需要以任何方式引用它,例如custordersordersCUSTordERsordERSCUSTORDERSORDERSCustOrdersOrders - 没问题。但是,如果您将任何名称(过程、table、列、...)括在双引号中,您 必须 在任何时候引用该对象时使用双引号,包括在与创建该对象时完全相同的双引号和匹配的字母大小写。

因此:要么将过程重新创建为 CREATE OR REPLACE PROCEDURE CustOrdersOrders(这是我的建议),要么使用双引号。