将 ODP.Net 与 NHibernate 与 .net System.decimal 一起使用

Posted

技术标签:

【中文标题】将 ODP.Net 与 NHibernate 与 .net System.decimal 一起使用【英文标题】:Using ODP.Net with NHibernate with .net System.decimal 【发布时间】:2011-05-17 23:41:16 【问题描述】:

我正在使用 ODP.net 针对 Oracle 10g 数据库运行聚合 AVG。我直接在数据库上运行这个查询,它工作正常:

从 IHObjekt 中选择 avg(ANSCHAFFUNGSKST)

返回:13.4493973163521

HQL 和 CreateCriteria 接口均成功执行查询。我收到 NHibernate '无法执行查询' 消息。但是,我相对确定这是基于 posting 的 ODP.Net 错误。

Oracle 有一个解决方案,只需 TRUNC AVG。但是,TRUNC 命令在 Oracle 和 SQL Server 中是不同的,我需要/不想让我的代码成为特定于数据库的代码。

关于如何减少小数点数以使其适合小数,最重要的是,它适用于所有数据库的任何想法?

来源 = NHibernate

堆栈跟踪

NHibernate.Loader.Loader.DoList(ISessionImplementor session, QueryParameters queryParameters) NHibernate.Loader.Loader.ListIgnoreQueryCache(ISessionImplementor session, QueryParameters queryParameters) NHibernate.Loader.Loader.List(ISessionImplementor session, QueryParameters queryParameters, ISet`1 querySpaces, IType[] resultTypes) NHibernate.Hql.Ast.ANTLR.Loader.QueryLoader.List(ISessionImplementor session, QueryParameters queryParameters) NHibernate.Hql.Ast.ANTLR.QueryTranslatorImpl.List(ISessionImplementor session, QueryParameters queryParameters) NHibernate.Engine.Query.HQLQueryPlan.PerformList(QueryParameters queryParameters, ISessionImplementor session, IList results) NHibernate.Impl.SessionImpl.List(String query, QueryParameters queryParameters, IList results) NHibernate.Impl.SessionImpl.List(字符串查询,QueryParameters 参数) NHibernate.Impl.QueryImpl.List() DBTest_NHibernate.MainWindow.ButtonHQLQuery_Click(Object sender, RoutedEventArgs e) in C:\...

内部异常

[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[] names, ISessionImplementor session, Object owner) NHibernate.Hql.Ast.ANTLR.Loader.QueryLoader.GetResultColumnOrRow(Object[] row, IResultTransformer resultTransformer, IDataReader rs, ISessionImplementor session) NHibernate.Loader.Loader.GetRowFromResultSet(IDataReader resultSet, ISessionImplementor session, QueryParameters queryParameters, LockMode[] lockModeArray, EntityKey optionalObjectKey, IList hydradObjects, EntityKey[] 键, Boolean returnProxies) NHibernate.Loader.Loader.DoQuery(ISessionImplementor session, QueryParameters queryParameters, Boolean returnProxies) NHibernate.Loader.Loader.DoQueryAndInitializeNonLazyCollections(ISessionImplementor session, QueryParameters queryParameters, Boolean returnProxies) NHibernate.Loader.Loader.DoList(ISessionImplementor session, QueryParameters queryParameters)

部分 HQL 测试结果

从 IHObjekt 中选择 TRUNC(AVG(ANSCHAFFUNGSKST),27) - WORKS(仅在 ORACLE 中) 从 IHObjekt 中选择 TRUNC(AVG(ANSCHAFFUNGSKST),28) - 不起作用 从 IHObjekt 中选择 AVG(ANSCHAFFUNGSKST) - 不起作用

NHibernate 生成的 SQL

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 在使用 ODP.Net 的 Oracle 上的上述 SQL 语句中不起作用。使用 SQL Server 或 Oracle 客户端即可。

【问题讨论】:

发布完整的异常,包括堆栈跟踪。 能贴出nhiberate生成的查询吗? 【参考方案1】:

通过剖析我得到的代码并将其切割成更小的部分,我可以确认,在使用逗号右侧数字过多的双精度时会遇到问题。

与 OP 相比,TRUNC(AVG(XXXX)) 在我的情况下不起作用。然而:

TRUNC(doubledigit, intvalue) 和 ROUND(doubledigit, intvalue)

带来了解决方案。我使用 odp.net 使用 nhibernate 和一个简单的 OracleDataReader 对此进行了测试

【讨论】:

【参考方案2】:

问题是由于小数点后的值的数量,返回的值不会转换为 .Net Decimal。看起来即使值被.Net四舍五入,Oracle内部也会抛出溢出异常。

从我所阅读的内容来看,Oracle 已确认这是设计使然,不会更改。

有些人使用 Trunc 或 cating 到一个字符串然后一个 double 来解决这个问题。

【讨论】:

感谢您的输入,但我的目标是防止系统包含特定于数据库的代码。该查询直接在 SQL Server 和 Oracle 上运行,但不能通过 ODP.Net。

以上是关于将 ODP.Net 与 NHibernate 与 .net System.decimal 一起使用的主要内容,如果未能解决你的问题,请参考以下文章

ODP.NET可以使用实体框架工具支持LDAP吗?

EF for Oracle,dotConnect for Oracle,ODP.NET

将 System.Data.OracleClient 替换为 Oracle.DataAccess (ODP.NET)

如何使用 ODP.Net 传递字节数组?

odp.net 可以将参数传递给布尔 pl/sql 参数吗?

在 odp.net 上使用带有 number 属性的 oracle 对象类型