如果列类型为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()将此sproc中的记录映射到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并使用vanilla 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()从阅读器中提取数据,如上所述,它失败了。 / p>
有关如何修补Dapper的任何建议吗?非常感谢。
更新:
经过反思,我RTFMed:第3节,"从OracleDataReader对象获取数据" Oracle Data Provider for .NET Developer’s Guide的解释。对于NUMBER列,ODP.NET的OracleDataReader将尝试从Byte到Decimal的一系列.NET类型以防止溢出。但是NUMBER可能仍会溢出Decimal,如果您尝试使用任何读者的.NET类型访问器(GetValue()/ GetValues()),则会产生无效的强制转换异常,在这种情况下,您必须使用阅读器' s ODP.NET类型访问器GetProviderSpecificValue(),它给你一个OracleDecimal,如果它溢出一个Decimal,它的Value属性将给你一个溢出异常,你唯一的办法就是用OracleDecimal&#39强制它进入一个较小的类型。 ; s ToXxx()方法。
但是当然ODP.NET类型访问器不是Dapper用来保存读取器对象的IDataReader接口的一部分,所以当列类型溢出所有.NET类型时,似乎Dapper本身与Oracle不兼容。 。
问题仍然存在 - 聪明的人是否知道如何扩展Dapper来处理这个问题。在我看来,我需要一个扩展点,我可以提供有关如何使用阅读器的实现(强制它使用GetDouble()而不是GetValue(),或者转换为OracleDataReader并调用GetProviderSpecificValue()) POCO属性或列类型。
答案 0 :(得分:0)
为了避免这个问题,我使用了:
CAST(COLUMN AS BINARY_DOUBLE)
或
TO_BINARY_DOUBLE(COLUMN)
在列出的here类型的Oracle中,它被描述为:
64位浮点数。此数据类型需要9个字节,包括长度字节。
Oracle使用的大多数其他数字类型最多为22个字节,因此这与.NET相同[/ p>]