Mybatis.NET Oracle 线上神奇问题:Value does not fall within the expected range.
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.的更多相关文章
- Spring+SpringMVC+MyBatis+easyUI整合进阶篇(七)一次线上Mysql数据库崩溃事故的记录
作者:13 GitHub:https://github.com/ZHENFENG13 版权声明:本文为原创文章,未经允许不得转载. 文章简介 工作这几年,技术栈在不断更新,项目管理心得也增加了不少,写 ...
- Spring+SpringMVC+MyBatis+easyUI整合进阶篇(八)线上Mysql数据库崩溃事故的原因和处理
前文提要 承接前文<一次线上Mysql数据库崩溃事故的记录>,在文章中讲到了一次线上数据库崩溃的事件记录,建议两篇文章结合在一起看,不至于摸不着头脑. 由于时间原因,其中只讲了当时的一些经 ...
- DBAplus社群线上分享----Sharding-Sphere之Proxy初探
功能 Cobar Mycat Heisenberg Shark TDDL Sharding-JDBC 是否开源 开源 开源 开源 开源 部分开源 开源 架构模型 Proxy架构 Proxy架构 Pro ...
- Springcloud及Git线上配置详解
SpringCloud 这个阶段该如何学? 三层架构 + MVC 框架: Spring IOC AOP SpringBoot,新一代的JavaEE开发标准,自动装配 模块化~ all in one,代 ...
- 线上Linux服务器运维安全策略经验分享
线上Linux服务器运维安全策略经验分享 https://mp.weixin.qq.com/s?__biz=MjM5NTU2MTQwNA==&mid=402022683&idx=1&a ...
- gradle测试与线上打包
首先,第一反应理所当然的是profile : <?xml version="1.0" encoding="UTF-8"?> <beans xm ...
- 一次线上Mysql数据库崩溃事故的记录
文章简介 工作这几年,技术栈在不断更新,项目管理心得也增加了不少,写代码的速度也在提升,感觉很欣慰,毕竟是在一直进步,但是过程中也有许许多多的曲折,也踩过了数不尽的坑坑洼洼,从一个连百度都不知道用的萌 ...
- 线上Mysql数据库崩溃事故的原因和处理
前文提要 承接前文<一次线上Mysql数据库崩溃事故的记录>,在文章中讲到了一次线上数据库崩溃的事件记录,建议两篇文章结合在一起看,不至于摸不着头脑. 由于时间原因,其中只讲了当时的一些经 ...
- JVM 线上故障排查基本操作
# 前言 对于后端程序员,特别是 Java 程序员来讲,排查线上问题是不可避免的.各种 CPU 飚高,内存溢出,频繁 GC 等等,这些都是令人头疼的问题.楼主同样也遇到过这些问题,那么,遇到这些问题该 ...
随机推荐
- 【 Linux 】Systemd 使用说明(1)
1. 前言 在 CentOS 7 中使用 systemd 取代了 init 的启动模式,这样的更新换代有什么好处呢?首先需要对 init 和 systemd 有个概念的认识. 2. init 概述 在 ...
- iOS 多线程的简单理解(2) 队列 :串行 ,并行,MainQueue,GlobalQueue
多线程队列是装载线程任务的队形结构.(系统以先进先出的方式调度队列中的任务执行 FIFO).在GCD中有两种队列: 串行队列.并发队列. 队列 :串行队列.并发队列,全局主对列,全局并发队列 2.1. ...
- mysql存储过程demo
#删除存储过程 -- drop procedure if exists add_test; CREATE PROCEDURE add_test() begin #定义变量 declare client ...
- 在Django中template遇到 "context must be a dict rather
原代码: # 使用模板文件 # 1.加载模板文件,获取一个模板文件 temp = loader.get_template('booktest/index.html') # 2.定义模板上下文:给模板文 ...
- 安卓app和苹果app共用一个二维码
应项目要求,现在安卓app和苹果app共用一个二维码,对外提供下载: <html> <head> <meta http-equiv="Content-Type& ...
- lua . 命令收集
io.popen()## 原型:io.popen ([prog [, mode]]) 解释:在额外的进程中启动程序prog,并返回用于prog的文件句柄.通俗的来说就是使用这个函数可以调用一个命令(程 ...
- JVM(一) 内存结构
JVM内存结构 方法区(JDK8以上叫元空间)和堆为线程共享区,虚拟机栈.本地方法栈及程序计数器为线程独占区, 还有一个没有在下图中体现的叫做直接内存(Direct Memory),不受JVM GC ...
- js里typeof和instanceof和箭头表达式要注意的地方,以及其他
如果学过类似C#这样的语言,然后定义两个类class Mu{}和class Ku{},那么显然typeof Mu != typeof Ku的,但是在js里则不是这样,对于Mu和Ku的对象进行typeo ...
- Python--递归函数实现:多维嵌套字典数据无限遍历
原创:多层嵌套字典无限遍历,实现当value值以特殊字符$开头,并且等于某项值时,用随机函数替换该参数 """处理前的字典{'patient': {'avatarPic' ...
- BC26模组UDP调试
BC26模组调试 数据上报AT流程 [15:33:46.819]收←◆ F1: 0000 0000 V0: 0000 0000 [0001] 00: 0006 000C 01: 0000 0000 U ...