gpt4 book ai didi

dapper - 如何将 Dapper micro-ORM 与 Oracle 结合使用来映射 NUMBER (OracleDecimal)

转载 作者:行者123 更新时间:2023-12-02 03:53:14 26 4
gpt4 key购买 nike

如果列类型为 NUMBER(x,y),ODP.NET 提供程序会在 IDataReader.GetValue()/GetValues() 中引发异常,从而导致所有 .NET 数字类型溢出。因此 Dapper 无法将此类列映射到 POCO 属性。

我有一个 Oracle 存储过程,它使用 REF CURSOR 输出参数返回 3 列记录。基本上所有 3 个都是 NUMBER(某物),但是 ODP.NET Oracle managed provider似乎决定将它们变成什么 ODP.NET 或 .NET 类型。

我在使用 Dapper 的 Query() 将记录从此存储过程映射到 POCO 时遇到问题。也许这实际上不是我的错,这一次 - 似乎当列出现为 ODP.NET 类型而不是 .NET 类型时,Dapper 就会失败。如果我从 POCO 中评论一个有问题的专栏,一切都会正常。

这里有一对行来说明:

--------------------------------------------------------------------
RDWY_LINK_ID RLC_LINK_OSET SIGN
---------------------- ---------------------- ----------------------
1829 1.51639964279667746989761971196153763602 1
14380 578.483600357203322530102380288038462364 -1

第一列在 .NET 中显示为 int,第二列显示为类型 OracleDecimal ,第三个为十进制。第二个是问题。

例如,暂时删除 Dapper 并使用普通 ODP.NET 访问这些记录就表明了问题:

int linkid = (int)reader.GetValue(0);
decimal linksign = (decimal)reader.GetValue(2);
//decimal dlinkoffset = (decimal)reader.GetValue(1); //**invalid cast exception at at Oracle.ManagedDataAccess.Client.OracleDataReader.GetDecimal(Int32 i)**
//object olinkoffset = reader.GetValue(1); //**same**
//decimal dlinkoffset = reader.GetDecimal(1); //**same**
//object[] values = new object[reader.FieldCount];
//reader.GetValues(values); //**same**
OracleDecimal linkoffset = (OracleDecimal)reader.GetProviderSpecificValue(1); //this works!
double dblinkoffset = reader.GetDouble(1); //interesting, this works too!
//decimal dlinkoffset = linkoffset.Value; //overflow exception
dblinkoffset = linkoffset.ToDouble(); //voila

我在 Dapper 的 SqlMapper.cs 文件中进行的少量浏览和断点显示,它正在使用 GetValue()/GetValues() 从读取器中提取数据,如上所述,但失败了。

有什么建议如何修补 Dapper 吗?非常感谢。

更新:

经过反射(reflection),我 RTFMed:Oracle Data Provider for .NET Developer’s Guide 的第 3 节“从 OracleDataReader 对象获取数据”这解释了。对于 NUMBER 列,ODP.NET 的 OracleDataReader 将尝试从 Byte 到 Decimal 的一系列 .NET 类型以防止溢出。但是,如果您尝试任何读取器的 .NET 类型访问器 (GetValue()/GetValues()),NUMBER 仍可能溢出 Decimal,从而给出无效的转换异常,在这种情况下,您必须使用读取器的 ODP.NET 类型访问器 GetProviderSpecificValue( ),它为您提供一个 OracleDecimal,如果它溢出 Decimal,其 Value 属性将为您提供溢出异常,您唯一的办法是使用 OracleDecimal 的 ToXxx() 方法之一将其强制转换为较小的类型。

但是,当然,ODP.NET 类型访问器不是 Dapper 用于保存读取器对象的 IDataReader 接口(interface)的一部分,因此当列类型将溢出所有 .NET 类型时,Dapper 本身似乎与 Oracle 不兼容。

问题仍然存在 - 聪明的人知道如何扩展 Dapper 来处理这个问题。在我看来,我需要一个扩展点,我可以在其中为某些 POCO 属性提供如何使用读取器的实现(强制它使用 GetDouble() 而不是 GetValue(),或转换为 OracleDataReader 并调用 GetProviderSpecificValue())或列类型。

最佳答案

为了避免这个问题,我使用了:

CAST(COLUMN AS BINARY_DOUBLE)

或者TO_BINARY_DOUBLE(COLUMN)

在 Oracle 类型中列出 here它被描述为:

64-bit floating point number. This datatype requires 9 bytes, including the length byte.

Oracle 使用的大多数其他数字类型最大为 22 字节,因此这对于 .NET 来说已经是最好的了

关于dapper - 如何将 Dapper micro-ORM 与 Oracle 结合使用来映射 NUMBER (OracleDecimal),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26131049/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com