Использование ODP.Net с NHibernate с .net System.decimal

Я использую ODP.net для запуска агрегированного AVG для базы данных Oracle 10g. Я запускаю этот запрос прямо в базе данных, и он отлично работает:

выберите avg (ANSCHAFFUNGSKST) из IHObjekt

он возвращает: 13,4493973163521

Ни интерфейсы HQL, ни интерфейсы CreateCriteria не успешно выполняют запрос. Я получаю сообщение NHibernate «Не удалось выполнить запрос». Однако я относительно уверен, что это ошибка ODP.Net на основании этой публикации.

Для Oracle есть решение, просто ОТРЕЗИТЕ AVG. Однако команда TRUNC отличается в Oracle от SQL Server, и мне нужно / хочу, чтобы мой код не зависел от конкретной базы данных.

Любые идеи о том, как я могу уменьшить количество десятичных знаков, чтобы оно соответствовало десятичной дроби и, что самое главное, работало во всех базах данных?

Источник = NHibernate

Трассировки стека

  • NHibernate.Loader.Loader.DoList (сеанс ISessionImplementor, QueryParameters queryParameters)
  • NHibernate.Loader.Loader.ListIgnoreQueryCache (сеанс ISessionImplementor, параметры запроса QueryParameters)
  • NHibernate.Loader.Loader.List (сеанс ISessionImplementor, QueryParameters queryParameters, ISet`1 querySpaces, IType [] resultTypes)
  • NHibernate.Hql.Ast.ANTLR.Loader.QueryLoader.List (сеанс ISessionImplementor, параметры запроса QueryParameters)
  • NHibernate.Hql.Ast.ANTLR.QueryTranslatorImpl.List (сеанс ISessionImplementor, параметры запроса QueryParameters)
  • NHibernate.Engine.Query.HQLQueryPlan.PerformList (QueryParameters queryParameters, сеанс ISessionImplementor, результаты IList)
  • NHibernate.Impl.SessionImpl.List (строковый запрос, параметры запроса, параметры запроса, результаты IList)
  • NHibernate.Impl.SessionImpl.List (строковый запрос, параметры QueryParameters)
  • NHibernate.Impl.QueryImpl.List ()
  • DBTest_NHibernate.MainWindow.ButtonHQLQuery_Click (отправитель объекта, RoutedEventArgs e) в C: \ ...

InnerException

[System.OverflowException] = {"Die arithmetische Operation hat einen Überlauf verursacht."} ... Арифметическая операция вызвала переполнение.

Источник = Oracle.DataAccess

Трассировки стека

  • Oracle.DataAccess.Types.DecimalConv.GetDecimal (IntPtr numCtx)
  • Oracle.DataAccess.Client.OracleDataReader.GetDecimal (Int32 i)
  • Oracle.DataAccess.Client.OracleDataReader.GetValue (Int32 i)
  • Oracle.DataAccess.Client.OracleDataReader.get_Item (Int32 i)
  • NHibernate.Type.DoubleType.Get (IDataReader rs, индекс Int32)
  • NHibernate.Type.NullableType.NullSafeGet (IDataReader rs, имя строки)
  • NHibernate.Type.NullableType.NullSafeGet (IDataReader rs, имена String [], сеанс ISessionImplementor, владелец объекта)
  • NHibernate.Hql.Ast.ANTLR.Loader.QueryLoader.GetResultColumnOrRow (строка Object [], IResultTransformer resultTransformer, IDataReader rs, сеанс ISessionImplementor)
  • NHibernate.Loader.Loader.GetRowFromResultSet (IDataReader resultSet, сеанс ISessionImplementor, QueryParameters queryParameters, LockMode [] lockModeArray, EntityKey optionalObjectKey, IList hydratedObjects, EntityKey [] keys, Boolean returnProxies)
  • NHibernate.Loader.Loader.DoQuery (сеанс ISessionImplementor, QueryParameters queryParameters, логическое returnProxies)
  • NHibernate.Loader.Loader.DoQueryAndInitializeNonLazyCollections (сеанс ISessionImplementor, QueryParameters queryParameters, логическое returnProxies)
  • NHibernate.Loader.Loader.DoList (сеанс ISessionImplementor, QueryParameters queryParameters)

Некоторые результаты тестирования HQL

  • выберите TRUNC (AVG (ANSCHAFFUNGSKST), 27) из IHObjekt - РАБОТАЕТ (ТОЛЬКО В ORACLE)
  • выберите TRUNC (AVG (ANSCHAFFUNGSKST), 28) из IHObjekt - НЕ РАБОТАЕТ
  • выбрать AVG (ANSCHAFFUNGSKST) от IHObjekt - НЕ РАБОТАЕТ

SQL, сгенерированный NHibernate

SELECT
    AVG(IHOBJEKT0_.ANSCHAFFUNGSKST) AS COL_0_0_,
    COUNT(IHOBJEKT0_.ANSCHAFFUNGSKST) AS COL_1_0_,
    MAX(IHOBJEKT0_.ANSCHAFFUNGSKST) AS COL_2_0_,
    MIN(IHOBJEKT0_.ANSCHAFFUNGSKST) AS COL_3_0_,
    SUM(IHOBJEKT0_.ANSCHAFFUNGSKST) AS COL_4_0_ 
FROM
    IHOBJEKT IHOBJEKT0_

Только AVG не работает в приведенном выше операторе SQL в Oracle, использующем ODP.Net. Используя SQL Server или клиент Oracle, он работает.


person Benjamin    schedule 30.11.2010    source источник
comment
Опубликуйте полное исключение, включая трассировку стека.   -  person Diego Mijelshon    schedule 30.11.2010
comment
Можете ли вы опубликовать запрос, сгенерированный nhiberate?   -  person Frederik Gheysels    schedule 01.12.2010


Ответы (2)


Анализируя предоставленный мне код и разрезая его на более мелкие части, я могу подтвердить, что вы столкнетесь с проблемами при использовании двойников с чрезмерным количеством цифр справа от запятой.

В отличие от OP, TRUNC (AVG (XXXX)) в моем случае не работал. Тем не мение:

TRUNC (двузначное, intvalue) и ROUND (двузначное, intvalue)

принес решение. Я тестировал это с помощью nhibernate и простого OracleDataReader, используя odp.net

person Marco    schedule 15.01.2013

Проблема связана с тем, что возвращаемое значение не будет преобразовано в .Net Decimal из-за количества значений после десятичной точки. Кажется, что даже несмотря на то, что значение округлено .Net, Oracle внутренне генерирует исключение переполнения.

Из того, что я прочитал, Oracle подтвердил, что это сделано намеренно и не будет изменено.

Некоторые люди используют Trunc или cating для строки, а затем double, чтобы обойти проблему.

person Russ    schedule 08.12.2010
comment
Спасибо за ввод, однако моя цель - уберечь систему от кода, специфичного для базы данных. Запрос работает на SQL Server и Oracle напрямую, но не через ODP.Net. - person Benjamin; 09.12.2010