1、错误现象

  在向数据库查询一条数据的时候报如下错误:

    Value does not fall within the expected range.
at Oracle.ManagedDataAccess.Client.OracleParameter.set_Value(Object value)
at MyBatis.DataMapper.Data.DefaultPreparedCommand.ApplyParameterMap(IDbProvider dbProvider, IDbCommand command, RequestScope request, IStatement statement, Object parameterObject)
at MyBatis.DataMapper.Data.DefaultPreparedCommand.Create(RequestScope request, ISession session, IStatement statement, Object parameterObject)
at MyBatis.DataMapper.MappedStatements.MappedStatement.Execute[T](Object preEvent, Object postEvent, ISession session, Object parameterObject, Func` requestRunner)
at MyBatis.DataMapper.MappedStatements.MappedStatement.ExecuteInsert(ISession session, Object parameterObject)
at MyBatis.DataMapper.DataMapper.Insert(String statementId, Object parameterObject)

 错误信息也很简单。在向OracleParameter的属性Value赋值时报错。

2、找不出的错误原因

  源码如下:

  

 [Category("Data"), Description(""), DefaultValue((string) null)]
public override object Value
{
get =>
this.m_value;
set
{
if (((value != null) && (value != DBNull.Value)) && (this.m_enumType == PrmEnumType.NOTSET))
{
Type type = value.GetType();
if (((type == typeof(sbyte)) || (type == typeof(ushort))) || ((type == typeof(uint)) || (type == typeof(ulong))))
{
throw new ArgumentException();
}
object obj2 = OraDb_DbTypeTable.s_table[type];
if ((obj2 == null) && type.IsArray)
{
obj2 = OraDb_DbTypeTable.s_table[type.GetElementType()];
}
if (obj2 == null)
{
throw new ArgumentException();
}
this.m_oraDbType = (OracleDbType) obj2;
this.m_bSetDbType = false;
this.m_enumType = PrmEnumType.VALUE;
}
this.m_value = value;
}
}

  从源码可以看到,报错可能出现在两个地方:if (((type == typeof(sbyte)) || (type == typeof(ushort))) || ((type == typeof(uint)) || (type == typeof(ulong))))【更老的驱动版本bool类型也不支持】 和 if (obj2 == null)。出现这个错误说明无法将C#类型映射为Oracle类型。

  首先检查第一处可能,发现插入报错的类中使用的类型有DateTime,DateTime?,long,int,string。发现第一处不满足。

  检查第二次可能,第二处取类型是从 OraDb_DbTypeTable 获取到的。源码如下:

  

 internal static void InsertTableEntries()
{
s_table.Add(typeof(byte), OracleDbType.Byte);
s_table.Add(typeof(byte[]), OracleDbType.Raw);
s_table.Add(typeof(char), OracleDbType.Varchar2);
s_table.Add(typeof(char[]), OracleDbType.Varchar2);
s_table.Add(typeof(DateTime), OracleDbType.TimeStamp);
s_table.Add(typeof(short), OracleDbType.Int16);
s_table.Add(typeof(int), OracleDbType.Int32);
s_table.Add(typeof(long), OracleDbType.Int64);
s_table.Add(typeof(float), OracleDbType.Single);
s_table.Add(typeof(double), OracleDbType.Double);
s_table.Add(typeof(decimal), OracleDbType.Decimal);
s_table.Add(typeof(string), OracleDbType.Varchar2);
s_table.Add(typeof(TimeSpan), OracleDbType.IntervalDS);
s_table.Add(typeof(OracleBFile), OracleDbType.BFile);
s_table.Add(typeof(OracleBinary), OracleDbType.Raw);
s_table.Add(typeof(OracleBlob), OracleDbType.Blob);
s_table.Add(typeof(OracleClob), OracleDbType.Clob);
s_table.Add(typeof(OracleDate), OracleDbType.Date);
s_table.Add(typeof(OracleDecimal), OracleDbType.Decimal);
s_table.Add(typeof(OracleIntervalDS), OracleDbType.IntervalDS);
s_table.Add(typeof(OracleIntervalYM), OracleDbType.IntervalYM);
s_table.Add(typeof(OracleRefCursor), OracleDbType.RefCursor);
s_table.Add(typeof(OracleString), OracleDbType.Varchar2);
s_table.Add(typeof(OracleTimeStamp), OracleDbType.TimeStamp);
s_table.Add(typeof(OracleTimeStampLTZ), OracleDbType.TimeStampLTZ);
s_table.Add(typeof(OracleTimeStampTZ), OracleDbType.TimeStampTZ);
s_table.Add(typeof(OracleXmlType), OracleDbType.XmlType);
s_table.Add(typeof(bool), OracleDbType.Boolean);
s_table.Add(typeof(DateTimeOffset), OracleDbType.TimeStampTZ);
}

  发现里面没有DateTime?,难道是这个地方不行。那也不对啊,其它地方同样类型是可以保存到数据库的啊。继续找下去在 MyBatis.DataMapper.Data.DefaultPreparedCommand.ApplyParameterMap 找到了信息。源码如下:

  

 public virtual void SetParameter(IDataParameter dataParameter, object parameterValue, string dbType)
{
if (parameterValue != null)
{
dataParameter.Value = parameterValue;
}
else
{
dataParameter.Value = DBNull.Value;
}
}

  如果值为null,会自动赋值为 DBNull.Value 也就会不会报错。既然都不会出现问题,可问题又会出现在哪里呢?

3、柳暗花明

  在本地尝试各种方法后仍然不能重现,只能让领导将生产程序包拷贝一份下来进行尝试。

  包拿到之后,进行必要配置启动,出现了新的诡异问题 Redis报错 :No connection is available to service this operation。仔细检查Redis配置发现问题。抓下内存快照看看实际配置信息是什么:

  

  看到这个一脸懵逼,Password竟然是null,明明已经配置了啊。查看了加载配置的源码,发现根本不会解析Password配置,还有这种操作,这程序包是有多老。弄好了Redis,启动保存数据,果然不行。反编译生产源码,发现惊天一幕:

  

  Id的类型竟然ulong。我擦这是多久没有更新了。原因至此是找到了。

4、吐槽

  这个服务是公司内部自己用的,很古老了。以前都是手工拷贝程序包发布的。最近由于公司发生了些意外事情,原来服务器不能用,需要部署新的服务器上。由于古老,不知道老大当时拿了多么古老的程序包部署了。

 

Mybatis.NET Oracle 线上神奇问题:Value does not fall within the expected range.的更多相关文章

  1. Spring+SpringMVC+MyBatis+easyUI整合进阶篇(七)一次线上Mysql数据库崩溃事故的记录

    作者:13 GitHub:https://github.com/ZHENFENG13 版权声明:本文为原创文章,未经允许不得转载. 文章简介 工作这几年,技术栈在不断更新,项目管理心得也增加了不少,写 ...

  2. Spring+SpringMVC+MyBatis+easyUI整合进阶篇(八)线上Mysql数据库崩溃事故的原因和处理

    前文提要 承接前文<一次线上Mysql数据库崩溃事故的记录>,在文章中讲到了一次线上数据库崩溃的事件记录,建议两篇文章结合在一起看,不至于摸不着头脑. 由于时间原因,其中只讲了当时的一些经 ...

  3. DBAplus社群线上分享----Sharding-Sphere之Proxy初探

    功能 Cobar Mycat Heisenberg Shark TDDL Sharding-JDBC 是否开源 开源 开源 开源 开源 部分开源 开源 架构模型 Proxy架构 Proxy架构 Pro ...

  4. Springcloud及Git线上配置详解

    SpringCloud 这个阶段该如何学? 三层架构 + MVC 框架: Spring IOC AOP SpringBoot,新一代的JavaEE开发标准,自动装配 模块化~ all in one,代 ...

  5. 线上Linux服务器运维安全策略经验分享

    线上Linux服务器运维安全策略经验分享 https://mp.weixin.qq.com/s?__biz=MjM5NTU2MTQwNA==&mid=402022683&idx=1&a ...

  6. gradle测试与线上打包

    首先,第一反应理所当然的是profile : <?xml version="1.0" encoding="UTF-8"?> <beans xm ...

  7. 一次线上Mysql数据库崩溃事故的记录

    文章简介 工作这几年,技术栈在不断更新,项目管理心得也增加了不少,写代码的速度也在提升,感觉很欣慰,毕竟是在一直进步,但是过程中也有许许多多的曲折,也踩过了数不尽的坑坑洼洼,从一个连百度都不知道用的萌 ...

  8. 线上Mysql数据库崩溃事故的原因和处理

    前文提要 承接前文<一次线上Mysql数据库崩溃事故的记录>,在文章中讲到了一次线上数据库崩溃的事件记录,建议两篇文章结合在一起看,不至于摸不着头脑. 由于时间原因,其中只讲了当时的一些经 ...

  9. JVM 线上故障排查基本操作

    # 前言 对于后端程序员,特别是 Java 程序员来讲,排查线上问题是不可避免的.各种 CPU 飚高,内存溢出,频繁 GC 等等,这些都是令人头疼的问题.楼主同样也遇到过这些问题,那么,遇到这些问题该 ...

随机推荐

  1. AWS 监控服务(六)

    AWS CloudWatch 概念 基于确定的内容监控基础设施组件 基于指定的指标发送通知并触发各种操作 分布式统计数据和收集系统,用于收集并跟踪指标 默认情况下,在管理程序级别无缝收集指标,如CPU ...

  2. 利用sourceinsight宏(Quicker.em)提高编码效率和质量

    利用sourceinsight宏(Quicker.em)提高编码效率和质量Marco是sourceinsight软件一个强大的功能,用户可以通过编写宏来实现自定义功能.这里有个比较流行的宏文件quic ...

  3. Meerkat软件

    一.准备工作 meerkat 0.189版本和以前的版本相比,支持bwa mem 输出的bam文件,还支持全外显子数据count SV. meerkat原理 1.1 需要准备的软件 unix/Linu ...

  4. PHP,Excel导出换行

    // 有id,才算真的有发票数据 if ($v['b_invoice_id']) { $v['b_invoice_info'] = json_decode($v['b_invoice_json'],t ...

  5. LeetCode 674. 最长连续递增序列(Longest Continuous Increasing Subsequence) 18

    674. 最长连续递增序列 674. Longest Continuous Increasing Subsequence 题目描述 给定一个未经排序的整型数组,找到最长且连续的递增序列. Given ...

  6. Duration和Period的区别--通俗易懂

    在jdk1.8以后,对表示日期时间的类型进行了重新分类,这里出现了2个新的类,Duraction 和Period Duraction表示:时间的区间,用来度量秒和纳秒之间的时间值 Period表示:一 ...

  7. [转帖]TPC-C解析系列04_TPC-C基准测试之数据库事务引擎的挑战

    TPC-C解析系列04_TPC-C基准测试之数据库事务引擎的挑战   http://www.itpub.net/2019/10/08/3331/ OceanBase这次TPC-C测试与榜单上Oracl ...

  8. 如何理解MVC

    在面试的时候,MVC这个概念考的次数很多,有许多人只能把三个字母解释成三个单词:model,view,controller,但是如果往深处说就说不出来什么东西了,对这个概念模糊不清,今天闲来无事看了一 ...

  9. echo、print和print_r的区别

    1.echo 可以输出一个或多个字符串 ,多个以逗号隔开就行 2.print 也可以输出一个或多个字符串 ,多个要用连接符 3.print_r()可以打印数组:对象 bool print_r ( mi ...

  10. PAT(B) 1088 三人行(Java)

    题目链接:1088 三人行 (20 point(s)) 参考博客:PAT (Basic Level) Practice (中文)1088 三人行 (20 分)(Java实现)吃口雪花 题目描述 子曰: ...