当我将基于DataRabbit的应用程序放到windows server 2008 SP1上运行时,抛出了System.AccessViolationException,提示信息为:“尝试读取或写入受保护的内存。这通常指示其他内存已损坏。”。而这个应用程序在windows server 2003上一直是非常正常的。根据异常的堆栈信息,可以知道是IORMapping<TEntity>.GetEntityFrom()方法抛出的,而IORMapping<TEntity>接口的实现是由Emit生成的动态类来完成的,而这个Emit工作了1年多一直没有出现过问题。
(关于为什么使用Emit请参见这篇文章:DataRabbit 轻量的数据访问框架(13)--DataRabbit 3.0 ORM性能大幅度提升! )
经过一段时间的摸索,终于发现是Emit将DataRow之中的bool字段赋值给对应的Entity字段时出现的,例如,Emit生成的代码类似这样:
if (row["IsVip"] != DBNull.Value)
{
member.IsVip= bool.Parse(row["IsVip"].ToString());
}
就是这段代码导致了在windows server 2008 SP1上的System.AccessViolationException ,于是我修改Emit,使其生成类似下面的代码就OK了:
if (row["IsVip"] != DBNull.Value)
{
member.IsVip= (bool)row["IsVip"];
}
如此问题解决了。更进一步,我想将所有的值类型都Emit出Cast代码直接进行转换,而不是通过Parse方法,很奇怪,当遇到Decimal类型时,就不行了,它抛出System.InvalidProgramException异常:“JIT编译器遇到内部限制”。看来并不是所有的值类型都能Emit 直接的Cast转换。不知“JIT编译器遇到内部限制”指的是JIT究竟遇到了什么限制?
更正后的DataRabbit的最新版本,我放到了DataRabbit 轻量的ORM框架(00) -- 序 的文末提供下载。
2008-09-21 正解:row["IsVip"]返回的是object,转换为值类型应该用unbox,而不是cast。