2

nhibernate を使用して ref カーソルを返す関数 (オラクル) を呼び出そうとしていますが、hbm ファイルでうまくいきません。

<return class ...構成エラーが発生するようにすると。

試してみ{ ? = call package.function(:a, :b, :c) as result from dual }ましたが、これでもうまくいきません。

4

4 に答える 4

4

nHibernate で ORACLE 関数/プロシージャを呼び出す場合、いくつかの制限があります。参照ドキュメント(17.2.2.1)
に記載されているとおり:

Oracle の場合、次の規則が適用されます

関数は結果セットを返す必要があります。プロシージャーの最初のパラメーターは、結果セットを返す OUT でなければなりません。これは、Oracle 9 または 10 で SYS_REFCURSOR タイプを使用して行われます。Oracle では、REF CURSOR タイプを定義する必要があります。Oracle の資料を参照してください。

私は同じ問題を抱えているので、少し遊んでみました。

パッケージ手順は次のとおりです。

頭:

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;

体:

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

この記事は、物事をどのように行う必要があるかを理解するのに役立ちました。

于 2012-02-23T12:13:34.703 に答える
1

この投稿に基づいて解決しますmapping-to-oracle-stored-procedure-with-fluent-nhibernate

ここに私の要約があります:

  1. プロシージャでは、 type の最初のパラメータを宣言する必要があります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 は「引数の数が正しくありません」という例外をスローします。

これが誰かに役立つことを願っています。

于 2013-04-05T15:33:31.820 に答える
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:

于 2013-01-18T15:26:09.540 に答える