IBatis.NET,不要相信它,内存疯狂泄漏

前不久为用户做了一个小工具,把数据中心的数据发布到其它相应的数据库.到用户的测试机上一跑, 10分钟左右,内存用光(1.5G),跟踪看了一下 IBATISN.NET 1.6.1的源码,哈哈。。。找着根了

一、根位置 MappedStatement.cs
ibaits的数据真实操作都交给了这个类。其中用一大堆与select相关操作的方法以及insert update delete相关方法,内存泄漏就在这些方法上。简单看一下ExecuteInsert(insert)方法的代码:
// 初始化 command 的参数
_preparedCommand.Create(request, session, this.Statement, parameterObject);
// 用 using 处理 command 
using (IDbCommand command = request.IDbCommand)
{
   try
    {
   if (_statement is Insert)
    {
        generatedKey = command.ExecuteNonQuery();
    }
    // Retrieve output parameter if the result class is specified
    else if (_statement is Procedure && (_statement.ResultClass != null) &&
            _sqlMap.TypeHandlerFactory.IsSimpleType(_statement.ResultClass))
    {
......// 省
    }

    if (selectKeyStatement != null && selectKeyStatement.isAfter)
    {
        IMappedStatement mappedStatement = _sqlMap.GetMappedStatement(selectKeyStatement.Id);
        generatedKey = mappedStatement.ExecuteQueryForObject(session, parameterObject);

        ObjectProbe.SetMemberValue(parameterObject, selectKeyStatement.PropertyName, generatedKey,
            request.DataExchangeFactory.ObjectFactory,
            request.DataExchangeFactory.AccessorFactory);
    }

    //ExecutePostSelect(request);
    
    RetrieveOutputParameters(request, session, command, parameterObject);
}
// 下面这个 finally 段是我加上去的,我不确定 command 的 dispose是否会调用相关Paramters中对象相应的 dispose 方法,所以就用了下面这个,因为程序中显示大量IDataParamter  对象无法回收
finally 
{  
     if (command.Parameters.Count > 0){
         MethodInfo mi = command.Parameters[0].GetType().GetMethod("Dispose", BindingFlags.Instance | BindingFlags.Public);
         if (mi != null)
             for (int i = 0; i < command.Parameters.Count; i++)
                            mi.Invoke(command.Parameters[i], null);
         }
   command.Dispose();
}
}


二、原因 IDispose 接口得显示调用
using并不能释放这些非托管资源
三、解决方法:看上面代码

四、总结
以前用ibaits怎么就没有发现在呢?
我想这与项目的实际应用场景有关,问题一直都存在,只是没有显现吧了。
大多数据时候,用户的输入参数只有几个,相对较少,而且调用频度应该不高。
而这个应用场景走的却是另一个极端:
调用频度极高:
数据中心实时采集4家公司的数据,且数据更新高峰在开收盘前后,中午休市最为集中,每天的数据更新在3000K左右,这些数据要及时发布到5个数据库中
参数超多:
近200张表中有50多张账务相关的表字段个数在100到230之间

这些字段最终是要转换成 INSERT 与 UPDATE 语句中的参数, 怪不得程序显示超多OarcleParamter 对象无法回收,它不多才怪。。。

不过还好,加了上面的代码后,程序内存近期还没超过150M,多在100M左右

如果你也有用IBAITS.NET,你可要小心了。。

这个问题其实是由 IDispose 接口引起的, 不知道JAVA是什么样子,源码还没仔细看

JAVA版本的3.0出来时间也不短了,易用性比 IBATIS.NET 1.6.1 要强太多了。
不知道 .NET 版本的更新什么时候出。。。

你可能感兴趣的:(.net,ibatis)