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

时间:2011-05-05 17:13:48

标签: oracle nhibernate function sys-refcursor

我正在尝试使用返回引用游标的nhibernate来调用函数(oracle),但我对hbm文件没有成功,任何人都可以用这个来指导我。

如果我将其设为<return class ...我收到配置错误。

我尝试{ ? = call package.function(:a, :b, :c) as result from dual },即使这也无效。

4 个答案:

答案 0 :(得分:4)

使用nHibernate调用ORACLE函数/过程时存在一些限制 如reference documentation(17.2.2.1)中所述:

  

对于Oracle,以下规则适用

     

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

由于遇到同样的问题,我试图用它来玩一点。

这是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;

这是我的映射文件:

<?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帮助我了解必须如何做。

答案 1 :(得分:1)

我根据这篇文章mapping-to-oracle-stored-procedure-with-fluent-nhibernate

解决了这个问题

以下是我的总结:

  1. 在此过程中,您必须声明类型为OUT SYS_REFCURSOR的第一个参数。例如:p_cursor OUT SYS_REFCURSOR, MyVar1 int, MyVar2 nvarchar
  2. 要返回结果集

    OPEN p_cursor FOR <select statement here>;
    
    在我的案例中,

    是一个动态查询,它就像一个魅力。

  3. 在hbm映射中围绕

    之间的调用
    { }
    

    前:

     { call MyProc (MyVar1, MyVar2) }
    

    如果您不使用{ },则nhibernate会抛出“参数数量不正确”的异常。

  4. 我希望这有助于某人。

答案 2 :(得分:0)

在我和Oracle上使用相同的东西,NHibernate似乎在程序包内部松开了程序的名称。所以我们先假设一个例子:call MYPACKAGE.usp_GetOrders ( :pCompanyCode , :pOrderNumer ) - &gt;包MyPackage不是存储过程的结果。

  

警告:Oracle.DataAccess.Client.OracleException ORA-06550:第1行第7列:PLS-00221:'MYPACKAGE'不是程序或未定义ORA-06550:第1行第7列:

答案 3 :(得分:-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#&GT;

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

最好的问候。