2012-02-22 61 views
0

我有一个ORACLE包,它只接收少量参数并返回一个其他(输出)参数 - 唯一值(数字)。
这里是封装代码:使用输出参数调用PROCEDURE

create or replace 
PACKAGE BODY   "USP_SHIPMENTS" AS 

    PROCEDURE usp_GetNewShipmentNumber 
    (
    pErrorCode OUT NUMBER, 
    pMessage OUT VARCHAR2,  
    pCompanyCode IN CHAR, 
    pNumber OUT VARCHAR2 
    ) 

    IS 

     BEGIN 

    pErrorCode := 0; 

     UPDATE 
     UTSASHN 
     SET 
     UTSASHN.UTSHNCOR = UTSASHN.UTSHNCOR + 1 
     WHERE 
     UTSASHN.UTSHCOSC = pCompanyCode AND UTSASHN.UTSHTIPO = 'S***' 
    RETURNING 
     CONCAT(TRIM(UTSASHN.UTSHDESC) , TRIM(to_char(UTSASHN.UTSHNCOR, '000000'))) INTO pNumber; 

    EXCEPTION 
     WHEN OTHERS THEN 
       pErrorCode := SQLCODE; 
       ROLLBACK; 

    END usp_GetNewShipmentNumber; 

END USP_SHIPMENTS; 

我一直在使用ODP.NET采用这种封装形式很长一段时间,一切都一直工作正常。
现在我正在开发一个新的应用程序与nHibernate 3.1.0.4000。 到目前为止,我已经能够映射我所有的实体并执行常规查询。一切正常。
我正试图调用这个包,但我一直在获取错误。

这是程序的映射:

<?xml version="1.0" encoding="utf-8"?> 
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="BpSpedizioni" namespace="BpSpedizioni.Domain"> 
    <sql-query name="GetNewShipmentNumber"> 
     { call USP_SHIPMENTS.usp_GetNewShipmentNumber (:pErrorCode, :pMessage, :pCompanyCode, :pNumber) } 
    </sql-query> 
</hibernate-mapping> 

,这是呼叫:

Session.GetNamedQuery("GetNewShipmentNumber") 
     .SetParameter("pErrorCode", "") 
     .SetParameter("pMessage", "") 
     .SetParameter<string>("pCompanyCode", "HBP00") 
     .SetParameter("pNumber", 0) 
     .UniqueResult(); 

我已经与.UniqueResult().ExecuteUpdate().List()尝试,但我只能得到例外:

could not execute query 
[ USP_SHIPMENTS.usp_GetNewShipmentNumber ] 
    Name:pErrorCode - Value: Name:pMessage - Value: Name:pCompanyCode - Value:HBP00 Name:pNumber - Value:0 
[SQL: USP_SHIPMENTS.usp_GetNewShipmentNumber] 

这是InnerException:

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

我搞不​​清楚我做错了什么! 有没有人可以帮助我?

+1

那么你[不能直接与SQL服务器](http://stackoverflow.com/questions/6138389/nhibernate-returning-an-output-parameter-from-a-mapped-stored-procedure)否为什么oracle会有所不同,但我可能是错的。 – 2012-02-22 19:25:43

+1

我对nhibernate和odp.net一无所知,但输出参数可能是个问题。也许如果你重写一个函数来返回错误代码,消息和数字[返回表类型](http://www.adp-gmbh.ch/ora/plsql/coll/return_table.html)? – winkbrace 2012-02-22 20:54:02

+0

@alfasin:当然,我有我的包装的头。我没有把它放在这里,因为不需要显示签名。谁说你的包装里不能有程序? http://docs.oracle.com/cd/B10501_01/appdev.920/a96624/09_packs.htm。无论如何,你错过了这一点。正如我所说,这个软件包可以正常工作并且正在使用中。你应该正确地阅读这个问题。除非你想继续检查我的软件包中的“错误”。 – LeftyX 2012-02-23 08:54:19

回答

4

我设法让它工作。 它可能不是最好的解决方案,但它的工作原理。

这是我对ORACLE PROCEDURE映射:

<?xml version="1.0" encoding="utf-8"?> 
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="MyAssembly"> 
    <sql-query name="GetNewShipmentNumber"> 
     { call MY_PACKAGE.usp_GetNewShipmentNumber (:pCompanyCode) } 
    </sql-query> 
</hibernate-mapping> 

和这个ORACLE PACKAGE

部首:

create or replace 
PACKAGE   "MY_PACKAGE" AS 

    TYPE ReferenceCursor IS REF CURSOR; 

    PROCEDURE usp_GetNewShipmentNumber 
     (
     pCursor OUT ReferenceCursor, 
     pCompanyCode IN CHAR 
     ); 

END MY_PACKAGE; 

BODY:

create or replace 
PACKAGE BODY   "MY_PACKAGE" AS 

PROCEDURE usp_GetNewShipmentNumber 
    (
     pCursor OUT ReferenceCursor, 
     pCompanyCode IN CHAR 
    ) 

IS 

    err_code NUMBER := 0; 
    err_msg VARCHAR2(200) := ''; 
    ShipmentNumber VARCHAR2(10); 

    BEGIN 

    UPDATE 
     UTSASHN 
    SET 
     UTSASHN.UTSHNCOR = UTSASHN.UTSHNCOR + 1 
    WHERE 
     UTSASHN.UTSHCOSC = pCompanyCode AND UTSASHN.UTSHTIPO = 'S***' 
    RETURNING 
     CONCAT(TRIM(UTSASHN.UTSHDESC) , TRIM(to_char(UTSASHN.UTSHNCOR, '000000'))) INTO ShipmentNumber; 

    OPEN pCursor FOR 
      SELECT ShipmentNumber AS DeliveryNoteNumber, err_code AS ErrorCode, err_msg AS ErrorMessage FROM DUAL; 

    EXCEPTION 
     WHEN OTHERS THEN 
      err_code := SQLCODE; 
      err_msg := substr(SQLERRM, 1, 200); 
      ROLLBACK; 

    OPEN pCursor FOR 
      SELECT '' AS DeliveryNoteNumber, err_code AS ErrorCode, err_msg AS ErrorMessage FROM DUAL; 

END usp_GetNewShipmentNumber; 

END MY_PACKAGE; 

正如你所看到的,我摆脱了返回参数,显然,它们不适用于nHibernate。
改为返回REF CURSOR

甲REF CURSOR必须始终是在封装(documentation(17.2.2.1))

对于Oracle的第一个参数,适用下列规则

的函数必须返回一个结果集。 过程的第一个参数必须是返回结果集的OUT。这是通过在Oracle 9或10中使用SYS_REFCURSOR类型 完成的。在Oracle中,您需要定义一个REF CURSOR类型的 ,请参见Oracle文献。

因为我想返回唯一结果,我管理一个复杂的类型,我创建了一个类:

public class NewDeliveryNoteNumber 
{ 
    public string DELIVERYNOTENUMBER { get; set; } 
    public decimal ERRORCODE { get; set; } 
    public string ERRORMESSAGE { get; set; } 
} 

,这将很容易地填充像这样:

using (var tx = Session.BeginTransaction()) 
    { 
    var x = Session.GetNamedQuery("GetNewShipmentNumber") 
     .SetParameter<string>("pCompanyCode", "ABC") 
     .SetResultTransformer(Transformers.AliasToBean<NewDeliveryNoteNumber>()) 
     .UniqueResult<NewDeliveryNoteNumber>(); 

    tx.Commit(); 
    } 

如果有人感兴趣,我试着用更多的infos回答另一个问题。