0

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

SQL

文件 1:

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

文件 2

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

这两个文件都在 SQL*Plus 中作为@"path\to\file1.sql".

代码

这是使用企业库数据访问应用程序块,它最终包装了 ADO.NET API。

DatabaseProviderFactory factory = new DatabaseProviderFactory(...); //this gets a custom configuration source
Database db = factory.Create("OracleTest");
DbCommand storedProcedure = db.GetStoredProcCommand("CustOrdersOrders");
DbConnection connection = db.CreateConnection();
connection.Open();
storedProcedure.Connection = connection;
db.DiscoverParameters(storedProcedure); //this ultimately calls OracleCommandBuilder.DeriveParameters(), which throws the exception.

当我使用相同的连接运行直接 SQL 查询时,它们会成功。

更多细节

这实际上是为数据访问应用程序块编写的单元测试的一部分,我在这里分叉以试图恢复这个库。这就是它使用System.Data.OracleClientODP.NET 而不是 ODP.NET 的原因。https://github.com/tsahi/data-access-application-block/blob/master/source/Tests/Oracle.Tests.VSTS/OracleParameterDiscoveryFixture.cs上的整套测试以类似的方式中断。

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

更新

在@madreflection 提出问题之后,是的,以下代码运行正确:

Database db = DatabaseFactory.CreateDatabase("OracleTest");
string spName = "AddCountry";
DbCommand dbCommand = db.GetStoredProcCommand(spName);
db.AddInParameter(dbCommand, "vCountryCode", DbType.String);
db.AddInParameter(dbCommand, "vCountryName", DbType.String);
db.SetParameterValue(dbCommand, "vCountryCode", "UK");
db.SetParameterValue(dbCommand, "vCountryName", "United Kingdom");

db.ExecuteNonQuery(dbCommand);

using (DataSet ds = db.ExecuteDataSet(CommandType.Text, "select * from Country where CountryCode='UK'"))
{
    Assert.IsTrue(1 == ds.Tables[0].Rows.Count);
    Assert.AreEqual("United Kingdom", ds.Tables[0].Rows[0]["CountryName"].ToString().Trim());
}

其中“AddCountry”定义为

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

不过,有趣的是,在这种情况下,OracleDatabasedbEntlibTest

CREATE OR REPLACE PACKAGE EntlibTest AS

PROCEDURE GetProductDetailsById
(vProductID IN NUMBER,vProductName OUT VARCHAR2,vUnitPrice OUT NUMBER);

END EntlibTest;
/

然后有另一个文件定义了这个过程的主体

CREATE OR REPLACE PACKAGE BODY EntlibTest AS

PROCEDURE GetProductDetailsById
(vProductID IN NUMBER,vProductName OUT VARCHAR2,vUnitPrice OUT NUMBER)
AS

BEGIN
    SELECT ProductName,UnitPrice INTO vProductName,vUnitPrice FROM Products where ProductId = vProductId;
END;

END EntlibTest;
/
4

0 回答 0