nhibernate, вызывает функцию в Oracle, которая возвращает sys refcursor - PullRequest
2 голосов
/ 05 мая 2011

Я пытаюсь вызвать функцию (оракул), используя nhibernate, который возвращает курсор ref, но я не смог выполнить файл hbm, может кто-нибудь, пожалуйста, подскажите мне об этом.

Если я сделаю это как <return class ... Я получаю ошибку конфигурации.

Я пытался { ? = call package.function(:a, :b, :c) as result from dual }, даже это тоже не работает.

Ответы [ 4 ]

4 голосов
/ 23 февраля 2012

Существуют некоторые ограничения при вызове функций / процедур ORACLE с помощью nHibernate.
Как указано в справочной документации (17.2.2.1):

ДляВ Oracle применяются следующие правила :

Функция должна возвращать набор результатов.Первый параметр процедуры должен быть OUT, который возвращает набор результатов.Это делается с помощью типа SYS_REFCURSOR в Oracle 9 или 10. В 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>();

Эта статья помогла мне понять, как все должно быть сделано.

1 голос
/ 05 апреля 2013

Я решаю это, основываясь на этом посте отображение хранимой процедуры-оракула-с-беглым-nhibernate

Вот мое резюме:

  1. В процедуре вы должны объявить первый параметр типа OUT SYS_REFCURSOR.Например: p_cursor OUT SYS_REFCURSOR, MyVar1 int, MyVar2 nvarchar
  2. Чтобы вернуть результат, выполните

    OPEN p_cursor FOR <select statement here>;
    

    , в моем случае это был динамический запрос, и он работает как чудо.

  3. В отображении hbm вызов между

    { }
    

    ex:

     { call MyProc (MyVar1, MyVar2) }
    

    Если вы не используете { }, nhibernate выбрасывает исключение «неверное числоаргументы ".

Надеюсь, это кому-нибудь поможет.

0 голосов
/ 10 апреля 2013

У меня такая же проблема.Я решил это так:

Oracle PL / SQL в MyPackage:

...
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 голосов
/ 18 января 2013

Учитывая то же самое на моей стороне и в Oracle, NHibernate, похоже, теряет название процедуры внутри пакета. Итак, давайте предположим пример: call MYPACKAGE.usp_GetOrders ( :pCompanyCode , :pOrderNumer ) -> результат, что пакет MyPackage не является хранимой процедурой.

ПРЕДУПРЕЖДЕНИЕ: Oracle.DataAccess.Client.OracleException ORA-06550: строка 1, столбец 7: PLS-00221: «MYPACKAGE» не является процедурой или не определена ORA-06550: строка 1, столбец 7:

...