事情是这样的, 最近需要开发Orcale的数据库.
于是使用了EF 加上 Oracle.ManagedDataAccess.Client
这个Oracle.ManagedDataAccess 很好用, 不需要orcale 客户端就能用.
但是这个类库有个地方不是非常好用. 数据读取出了问题,它的提示非常非常让人气愤. 啥调试信息都没有..只有一个提示 “类型转换异常”.
大家经常遇到的. InvalidCastException
异常就异常呗, 问题是查找问题的信息太少了.
我不知道是哪条数据导致的这个问题.
如果有一万条数据. 其中某一条出错了. 我不是要崩溃了??
而且还不知道是哪个字段列出了问题…
具体是如何解决这个问题的? 咱们再细细谈来. 里面可多道道了…
准备好板凳哈..学会了, 你就不怕一些莫名其妙的异常了. 自己动手找问题点…百度什么的都是新手用的了…
首先出错了报异常, 肯定要捕获异常.
异常信息里面的StackTrace 非常详细的记录了出错的具体函数.
从图上可以看出.
在 Oracle.ManagedDataAccess.Client.OracleDataReader.GetString(Int32 i)
这个方法中因为读取第i个数据出错了.并且是转换为string.
Oracle.ManagedDataAccess 并没有公布源代码, 我们也不知道里面做了什么事情.
好吧,搬出.Net Reflector 先看看这个函数里面的代码是怎么写.
后来我反编译了.Oracle.ManagedDataAccess的源代码. 一看. 果然有2个InvalidCastException 第一个是有具体信息的.. 但是第二个就是光溜溜的InvalidCastException 了. 我猜应该是第二个InvalidCastException了.
好吧,到现在为止. 我们也大概的知道了GetString(i)这个函数里面做了什么事情. 有几种情况会出这个异常..
好吧, 到这里有些大神估计就不会再调试了. 根据代码也能猜出来是那里的问题..
但是这个地方.我想知道是哪个列出了问题? internalType 在出错的时候是什么类型?
传入的参数 i 又是多少?
下面本文的主题关键来了… 如何知道这个方法的内部变量的值?
我曾经相关n多个方法, 其中包括继承重载,dll反编译重写, Trace取信息等等.方法.
结果都无法取到这个内部变量的值.再多种方法无果的情况下. 我把眼光转向了vs调试工具. 按道理说. vs调试时能取到我的变量的值,也自然能取到别人变量的值. 嗯….
如果你的代码是像我下面这样写的. 那么你的代码出错是肯定不能停止在下面的第2个箭头处.
正常应该是直接跳进第1个箭头的地方了.
好吧,本文的第一个重点. 要修改你的vs配置. vs的默认配置是不会像我的那样停止的.
具体配置是.
第一点. 源代码不可用时显示反汇编.. 这个是为什么要启用呢? 如果不启用你就无法调试内部变量了.
第二点. 如果启用了 仅我的代码 那么别人的代码也不会调试的.
另外插一句. 里面的两个三角形地方如果勾上了. 你就可以调试.net源代码了. 只是第一次调试要下载pdb符号文件比较慢. 所以我这里就去掉了.
好吧,上面两点设置好以后还有非常重要的第三点.
这个地方,查找到你要处理的异常….
勾上它, 勾上以后, 只要出现这种异常,程序立马停止. 进入中断状态. 而不会跑到你的catch 中…
为啥不能跑到你的catch中? 如果进入到你的catch以后. 那么很不幸. 你就无法调试具体出错函数的内部变量了. 已经被回收了..
所以这里也很重要.
OK到这里, 我们已经把设置都弄好了.
下面我们来试一下.如何取得变量信息. 里面还有点技巧哦..
程序跑起来, 直到出错…
上图已经比较明确了. 调试时的2个比较重要的窗口, 一个是调用堆栈,另外一个是局部变量. 这个局部变量会自动显示当前调用层的局部变量… 注意是当前调用层哦.
而且这个当前调用层可以改变的. 如何改变? 双击”调用堆栈” 的函数就可以改变当前的调用层了.
那么,我们来看一下. 在Oracle.ManagedDataAccess.Client.OracleDataReader.GetString(Int32 i)这个函数里面出错时的i 的数值是多少?
到这里, 基本上已经能解决绝大多数问题了…
但是有的时候我们还想知道其它的变量怎么办?
例如源代码里面的. internalType . 我想知道它是什么类型…
补个源代码的图,方便大家参考.
好啦,到此结束..
有了这个工具, 还有什么问题调试不出来?
要是.net能提供 捕捉监视的变量的dll 功能就好了.
方便程序员自动捕捉内容和变量值. 直接远程就能诊断程序了.