2012-02-22 62 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回答另一個問題。