简体   繁体   English

nhibernate,Oracle中的调用函数,它返回sys refcursor

[英]nhibernate, call function in Oracle which returns sys refcursor

I am trying to call a function (oracle) using nhibernate that return ref cursor, but i am not successful with the hbm file, can any one please guide me with this. 我正在尝试使用nhibernate调用返回ref游标的函数(oracle),但是我对hbm文件不成功,可以有人指导我这一点。

If i make it like <return class ... I am getting configuration error. 如果我将其设为<return class ...则会收到配置错误。

I tried { ? = call package.function(:a, :b, :c) as result from dual } 我试过{ ? = call package.function(:a, :b, :c) as result from dual } { ? = call package.function(:a, :b, :c) as result from dual } , even this is also not working. { ? = call package.function(:a, :b, :c) as result from dual } ,即使这样也不起作用。

There are some limitations when calling ORACLE functions/procedures with nHibernate. 用nHibernate调用ORACLE函数/过程时有一些限制。
As stated in the reference documentation (17.2.2.1): 参考文档 (17.2.2.1)中所述:

For Oracle the following rules apply : 对于Oracle,适用以下规则

A function must return a result set. 函数必须返回结果集。 The first parameter of a procedure must be an OUT that returns a result set. 过程的第一个参数必须是返回结果集的OUT。 This is done by using a SYS_REFCURSOR type in Oracle 9 or 10. In Oracle you need to define a REF CURSOR type, see Oracle literature. 这是通过在Oracle 9或10中使用SYS_REFCURSOR类型完成的。在Oracle中,您需要定义REF CURSOR类型,请参见Oracle文献。

I've tried to play a little bit with it as I am having the same problem. 我遇到了同样的问题,因此尝试尝试了一下。

Here is the PACKAGE-PROCEDURE: 这是包裹程序:

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;

This my mapping file: 这是我的映射文件:

<?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>

and this is the code I've used to test it: 这是我用来测试的代码:

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

As you can see the REF CURSOR must be the first parameter in your procedure ( pCursor OUT ReferenceCursor ) and you do not need to reference it in your mapping or your call. 如您所见,REF CURSOR必须是过程中的第一个参数( pCursor OUT ReferenceCursor ),您无需在映射或调用中引用它。

If you want to return entities, things get a little bit more complicated. 如果要返回实体,事情会变得有些复杂。

Your mapping file must specify the return type (class): 您的映射文件必须指定返回类型(类):

<?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>

You have to define your entity: 您必须定义您的实体:

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

and this is the mapping file for your entity: 这是您实体的映射文件:

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

This is my ORACLE package: 这是我的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;

And now you can easily get your orders using parameters: 现在,您可以使用参数轻松获得订单:

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

This article helped me to understand how thing must be done. 这篇文章帮助我了解了必须如何做。

I solve it basing on this post mapping-to-oracle-stored-procedure-with-fluent-nhibernate 我根据这篇文章与流利的hibernate映射到oracle存储过程来解决它

Here is my summary: 这是我的摘要:

  1. In the procedure you have to declare a first parameter of type OUT SYS_REFCURSOR . 在该过程中,您必须声明OUT SYS_REFCURSOR类型的第一个参数。 ex: p_cursor OUT SYS_REFCURSOR, MyVar1 int, MyVar2 nvarchar 例如: p_cursor OUT SYS_REFCURSOR, MyVar1 int, MyVar2 nvarchar
  2. To return the resulset do 要返回resulset,请执行

     OPEN p_cursor FOR <select statement here>; 

    in my case was a dynamic query and it works like a charm. 在我的情况下,它是一个动态查询,它就像一个超级按钮。

  3. In the hbm mapping surround the call between 在hbm映射周围,

     { } 

    ex: 例如:

      { call MyProc (MyVar1, MyVar2) } 

    If you do not use the { } , nhibernate throws exception of "incorrect number of arguments". 如果不使用{ } ,则nhibernate会抛出“参数数目错误”的异常。

I hope this helps someone. 我希望这可以帮助别人。

With the same thing on my side and on Oracle, NHibernate seems to loose the name of the procedure inside the package. 在我和Oracle方面都一样,NHibernate似乎在程序包中松了该过程的名称。 So let's suppose the example upfront: call MYPACKAGE.usp_GetOrders ( :pCompanyCode , :pOrderNumer ) --> result that the package MyPackage is not a stored procedure. 因此,让我们以前面的示例为例: call MYPACKAGE.usp_GetOrders ( :pCompanyCode , :pOrderNumer ) ->结果,包MyPackage不是存储过程。

WARN: Oracle.DataAccess.Client.OracleException ORA-06550: line 1, column 7: PLS-00221: 'MYPACKAGE' is not a procedure or is undefined ORA-06550: line 1, column 7: 警告:Oracle.DataAccess.Client.OracleException ORA-06550:第1行,第7列:PLS-00221:'MYPACKAGE'不是过程或未定义ORA-06550:第1行,第7列:

I got the same trouble. 我也遇到了同样的麻烦。 I solved it by this: 我通过以下方法解决了它:

Oracle PL/SQL in MyPackage: 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: (Embedded Resource) 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#> C#>

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

Best regards. 最好的祝福。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM