2011-05-05 34 views
2

我想調用一個函數(oracle)使用nhibernate返回參考光標,但我沒有成功的hbm文件,任何人都可以引導我與此。nhibernate,在Oracle返回sys調用函數返回sys refcursor

如果我讓它像<return class ...我得到配置錯誤。我試過{ ? = call package.function(:a, :b, :c) as result from dual },即使這樣也行不通。

+0

您的問題是否解決?我也很喜歡同樣的 – Vamsi 2011-07-19 11:14:39

回答

4

使用nHibernate調用ORACLE函數/過程時有一些限制。
正如reference documentation(17.2.2.1)指出:

對於Oracle有如下規則

函數必須返回一個結果集。 過程的第一個參數必須是返回結果集的OUT。這是通過在Oracle 9或10中使用SYS_REFCURSOR類型 完成的。在Oracle中,您需要定義一個REF CURSOR類型的 ,請參見Oracle文獻。

我試着玩一點它,因爲我有同樣的問題。

這裏是PACKAGE-程序:

HEAD:

create or replace 
PACKAGE   "MYPACKAGE" AS 

    TYPE ReferenceCursor IS REF CURSOR; 

    PROCEDURE usp_GetDual 
    (
    pCursor OUT ReferenceCursor, 
    a IN CHAR, 
    b IN CHAR 
    ); 

END MYPACKAGE; 

BODY:

PROCEDURE usp_GetDual 
    (
      pCursor OUT ReferenceCursor, 
      a IN CHAR, 
      b IN CHAR 
    ) 

    IS 

    err_code NUMBER; 
    err_msg VARCHAR2(200); 

    BEGIN 

    OPEN pCursor FOR 
    SELECT * FROM dual; 

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

END usp_GetDual; 

這是我的映射文件:

<?xml version="1.0" encoding="utf-8"?> 
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="MyAssembly"> 
    <sql-query name="GetDaul"> 
     { call MYPACKAGE.usp_GetDual (:a, :b) } 
    </sql-query> 
</hibernate-mapping> 

,這是我用來測試它的代碼:

var value = Session.GetNamedQuery("GetDaul") 
    .SetParameter<string>("a", "AAA") 
    .SetParameter<string>("b", "BBB") 
    .UniqueResult(); 

正如你可以看到REF CURSOR必須在你的程序中(pCursor OUT ReferenceCursor)的第一個參數,你不需要引用它你的地圖或你的電話。

如果你想返回實體,事情會變得更復雜一點。

映射文件必須指定返回類型(類):

<?xml version="1.0" encoding="utf-8"?> 
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="MyAssembly"> 
    <sql-query name="GetOrders"> 
     <return class="MyAssembly.Domain.MyOrder, MyAssembly" /> 
     { call MYPACKAGE.usp_GetOrders (:pCompanyCode , :pOrderNumer) } 
    </sql-query> 
</hibernate-mapping> 

你必須定義你的實體:

public class MyOrder 
{ 
    public virtual string Number { get; set; } 
    public virtual int Ver { get; private set; } 
    public virtual string Company { get; set; } 
    public virtual string Customer { get; set; } 

    public override bool Equals(object obj) 
    { 
     if (obj == null) 
      return false; 
     Order order = obj as Order; 
     if (order == null) 
      return false; 
     if (this.Number.Trim() == order.Number.Trim() && 
      this.Ver == order.Ver && 
      this.Company.Trim() == order.Company.Trim() 
      ) 
      return true; 
     else 
      return false; 
    } 

    public override int GetHashCode() 
    { 
     int hash = 0; 
     hash = hash + 
      (null == this.Number ? 0 : this.Number.GetHashCode()) 
      + 
      (this.Ver.GetHashCode()) 
      + 
      (null == this.Company ? 0 : this.Company.GetHashCode()); 

     return (hash); 
    } 
} 

,這是對你的實體的映射文件:

<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="MyAssembly" namespace="MyAssembly.Domain"> 
    <class name="MyOrder" table="OCSAORH" mutable="false"> 
    <composite-id> 
     <key-property name="Number" column="OCHORDN" type="String" length="10"></key-property> 
     <key-property name="Ver" column="OCHAMND" type="Int32"></key-property> 
     <key-property name="Company" column="OCHCOSC" type="String" length="5"></key-property> 
    </composite-id> 
    <property name="Customer" column="OCHCLII" type="String"></property> 
    </class> 
</hibernate-mapping> 

這是我的ORACLE包:

PROCEDURE usp_GetOrders 
      (
      pCursor OUT ReferenceCursor, 
      pCompanyCode IN CHAR, 
      pOrderNumer IN CHAR 
    ) 

    IS 

    err_code NUMBER; 
    err_msg VARCHAR2(200); 

    BEGIN 

    OPEN pCursor FOR 
     SELECT 
      OCSAORH.* 
     FROM OCSAORH 
      WHERE OCSAORH.OCHAMND = 0 
       AND OCSAORH.OCHCOSC = pCompanyCode 
       AND OCSAORH.OCHORDN = pOrderNumer;    
    EXCEPTION 
      WHEN OTHERS THEN 
      err_code := SQLCODE; 
      err_msg := substr(SQLERRM, 1, 200); 

END usp_GetOrders; 

現在你可以使用參數很容易地得到您的訂單:

var listOfOrders = Session.GetNamedQuery("GetOrder") 
    .SetParameter<string>("pCompanyCode", "ABC") 
     .SetParameter<string>("pOrderNumer", "XYZ") 
     .List<Domain.MyOrder>(); 

article幫助我瞭解一點必須怎樣做。

+0

文章很好。但是如果我們需要使用返回sys_refcursor的存儲函數(不是過程),我們該怎麼做? – Sash0k 2016-09-20 13:55:01

+0

@ Sash0k:這會很棘手。據我記得你不能這樣做,但事情可能已經改變。 – LeftyX 2016-09-20 14:22:10

+0

這幫了很大忙。如果出現錯誤 ORA-06553:PLS-306:調用PROCEDURE 時參數的數量或類型錯誤請確保以{}方式包裝呼叫,如下所示。 – Bret 2017-08-12 15:45:39

0

在我身邊和Oracle上,NHibernate似乎沒有包內的過程名稱。因此,我們假設前面的示例:call MYPACKAGE.usp_GetOrders (:pCompanyCode , :pOrderNumer) - >導致包MyPackage不是存儲過程。

WARN:Oracle.DataAccess.Client.OracleException ORA-06550:第1行,第7列:PLS-00221: 'mypackage的' 不是過程或未定義ORA-06550:第1行,第7列:

+0

您是否爲該包創建了同義詞? – 2013-06-25 05:09:07

1

我解決它立足於這個職位mapping-to-oracle-stored-procedure-with-fluent-nhibernate

這裏是我的總結:

  1. 在過程中,您必須聲明類型的第一個參數10。例如:p_cursor OUT SYS_REFCURSOR, MyVar1 int, MyVar2 nvarchar
  2. 要返回resulset做

    OPEN p_cursor FOR <select statement here>; 
    
    在我的情況

    是一個動態的查詢和它的作品就像一個魅力。

  3. 在HBM映射圍繞呼叫

    { } 
    

    EX之間:

    { call MyProc (MyVar1, MyVar2) } 
    

    如果不使用{ },NHibernate的拋出 「不正確的參數個數」 的例外。

我希望這可以幫助別人。

-1

我也遇到過同樣的麻煩。我解決它通過這樣的:在MyPackage的

的Oracle PL/SQL:

... 
function MyFunction(a number) return number is 
n number; 
pragma autonomous_transaction; -- Important! 
begin 
    n:=apps.fnd_request.submit_request(...); 
    commit; -- Important! 
    return n; 
end; 

mapping.hbm。XML:(嵌入的資源)

... 
    <sql-query name='MyFunctionQuery'> 
    <query-param name='par' type='System.Int64'/> 
    <return-scalar column='ret' type='System.Int64'/> 
    <![CDATA[ 
     select MyPackage.MyFunction(:par) as ret from dual 
    ]]> 
    </sql-query> 

C#>

... 
IQuery Q = session.GetNamedQuery("MyFunctionQuery") 
        .SetParameter("par", 1); 
var result = Q.UniqueResult(); 

問候。

+0

返回值是一個sys_refcursor,而不是標量值... – 2013-06-25 05:07:45