【发布时间】:2013-12-16 23:54:28
【问题描述】:
我在 NHibernate 和 ActiveRecord 中遇到了一种奇怪的内存泄漏情况。 我设计了一个系统来加载特定的实体列,以便将其转换为平面订单并通过网络传输它们。它托管在 IIS 中,用作多个销售点设备的中心点。
该系统适用于非常大量的实体,一次可达数百万。
它的工作原理基本上是确定实体元数据中需要哪些列,将其提取到投影并使用结果转换器执行查询。
我不确定发生了什么变化,但我遇到了一种情况,即我看到转换结果的内存泄漏,分析器告诉我实体被保存在类 Loader 的某个 List 中方法 DoQuery。我在那种方法中找不到任何会导致他们被关押的东西。
这是我用来获取行值的函数,它也用于加载我拥有的其他普通 NHibernate 实体:
public static IList GetResultsForCriteria(DetachedCriteria crit, int? maxResults,TransactionLockModeEnum transactionLockMode)
{
ISessionFactoryHolder holder = ActiveRecordMediator.GetSessionFactoryHolder();
ISession session = holder.CreateSession(typeof(object));
session.FlushMode = FlushMode.Never;
ITransaction transaction = null;
if (transactionLockMode == TransactionLockModeEnum.NonLocking)
{
transaction = session.BeginTransaction(IsolationLevel.ReadUncommitted);
}
ICriteria executableCriteria = crit.GetExecutableCriteria(session);
if (maxResults.HasValue)
{
executableCriteria.SetMaxResults(maxResults.Value);
}
IList results;
try
{
if (session.Connection.State == ConnectionState.Closed)
{
session.Connection.Open();
}
results = executableCriteria.List();
if (transaction != null)
{
transaction.Commit();
}
ConnectionMonitor.AddConnection(session.Connection);
}
finally
{
holder.ReleaseSession(session);
}
return results;
}
这是我用来将原始值转换为具有属性名称和值的字典的转换器:
class EntityRetrieverResultTransform : IResultTransformer
{
public object TransformTuple(object[] tuple, string[] aliases)
{
EntityFields fields = new EntityFields();
for (int i = 0; i < tuple.Length; i++)
{
string aliasName = aliases[i].Replace("[","").Replace("]","");
fields.Add(aliasName,tuple[i]);
}
return fields;
}
public IList TransformList(IList collection)
{
return collection;
}
}
EntityFields 类是一个简单的类:
public class EntityFields : Dictionary<string,object>
{
}
这是来自分析器的根图,用于 EntityFields 类的特定实例:
http://i.stack.imgur.com/U9ukC.png
正如您在 DoQuery 和 List 之间看到的那样,没有字段名称。
一开始我以为问题出在结果转换器上,但即使去掉它,我仍然看到原始值作为 string[] 的内存泄漏。
我做错了什么?为什么 EntityFields 实例被保存在会话中?
【问题讨论】:
标签: nhibernate activerecord memory-leaks