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. yaml中使用harbor

    1.在harbor的ui界面上注册一个账号 姓名:zihao 全名:zhuzihao 密码:Zihao@5tgb 邮箱:15613691030@163.com 2.在需要下载镜像的机器上,同样需要修改 ...

  2. html如何修改hr水平直线的粗细

    hr是常见的超文本标签,是一条水平直线,要设置该直线变粗一些.可以先把hr本身的border隐藏掉,然后设置border-top-width,也就是只留上边框,如图:hr的默认高度height是0,所 ...

  3. Java学习,从入门到放弃(二)Linux配置mvn

    其实网上的教程很多,随便拿一个,比如:https://www.cnblogs.com/chuijingjing/p/10430649.html 但在实践过程中,发现可能需要将JAVA_HOME也加到 ...

  4. Mathtype安装与最简破解

    1.MathType资源 链接: https://pan.baidu.com/s/1UapJCcfU7Me_rIWdAe5nfw   提取码:   1y9i 2.破解 我之前的30天试用期过了,没来得 ...

  5. php面向对象(目录操作)

    目录操作 创建目录 Mkdir(目录地址,权限,是否递归创建=false); Rmdir(目录地址) 删除目录 仅仅可以删除空目录.(不支持递归删除) 移动(改名) Rename(旧地址,新地址) 该 ...

  6. 哈希--Hash,“散列”/“哈希”

    哈希 Hash,翻译“散列”,音译为“哈希”,把任意长度的输入,通过散列算法,变换成固定长度的输出,该输出就是散列值.这种转换是一种压缩映射,也就是散列值的空间通常远小于输入的空间,不同的输入可能会散 ...

  7. 《Mysql - 读写分离有哪些坑?》

    一:读写分离 - 概念 -  读写分离的主要目标就是分摊主库的压力. - 基本架构 -     -  二:两种读写分离的架构特点 - 客户端直连方案 - 因为少了一层 proxy 转发,所以查询性能稍 ...

  8. awk简单使用

    1.awk格式 awk  [ 切割符号 ]  ' [ / pattern/ ]  函数语句 '   [ 文件名 ] 2.输出对应列 $0  全部 , $1 第一列  ,$2 第二列  ...... a ...

  9. k8s开发实践

    代码自动生成:https://blog.openshift.com/kubernetes-deep-dive-code-generation-customresources/ 自定义controlle ...

  10. 机器学习之逻辑回归(Logistic)笔记

    在说逻辑回归之前,可以先说一说逻辑回归与线性回归的区别: 逻辑回归与线性回归在学习规则形式上是完全一致的,它们的区别在于hθ(x(i))为什么样的函数 当hθ(x(i))=θTx(i)时,表示的是线性 ...