Oracle
 sql >> Baza danych >  >> RDS >> Oracle

nhibernate, wywołaj funkcję w Oracle, która zwraca refcursor sys

Istnieją pewne ograniczenia podczas wywoływania funkcji/procedur ORACLE za pomocą nHibernate.
Jak stwierdzono w dokumentacji referencyjnej (17.2.2.1):

W przypadku Oracle obowiązują następujące zasady :

Funkcja musi zwrócić zestaw wyników. Pierwszy parametr procedury musi być OUT, który zwraca zestaw wyników. Odbywa się to za pomocą typu SYS_REFCURSOR w Oracle 9 lub 10. W Oracle musisz zdefiniować typ REF CURSOR, patrz literatura Oracle.

Próbowałem się z tym trochę pobawić, ponieważ mam ten sam problem.

Oto PROCEDURA PAKIETU:

GŁOWA:

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;

KORPUS:

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;

To mój plik mapowania:

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

i to jest kod, którego użyłem do testowania:

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

Jak widać REF CURSOR musi być pierwszym parametrem w twojej procedurze (pCursor OUT ReferenceCursor ) i nie musisz odwoływać się do niego w swoim mapowaniu lub wywołaniu.

Jeśli chcesz zwrócić jednostki, sprawy stają się nieco bardziej skomplikowane.

Twój plik mapowania musi określać zwracany typ (klasa):

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

Musisz zdefiniować swoją jednostkę:

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

a to jest plik mapowania Twojej jednostki:

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

To jest mój pakiet 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;

A teraz możesz łatwo otrzymać swoje zamówienia za pomocą parametrów:

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

Ten artykuł pomógł mi zrozumieć, jak należy to zrobić.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Tworzenie wyzwalacza, który będzie uruchamiany tylko wtedy, gdy tworzona jest nowa tabela

  2. Jaka jest poprawna składnia adresu URL JDBC w przypadku korzystania z portfeli Oracle?

  3. Zapytanie SQL do przetłumaczenia listy liczb dopasowanych z kilku zakresów na listę wartości

  4. Jak działa klauzula „w” w Oracle?

  5. Jak formatować liczby ujemne za pomocą nawiasów kątowych w Oracle