Note that there are some explanatory texts on larger screens.

plurals
  1. POMemory leak with non nhibernate entities
    text
    copied!<p>I'm having a strange situation of a memory leak in NHibernate and ActiveRecord. I'm designed a system to load specific columns of entities in order to convert it to a flat order and transfer them over the network. It's hosted in IIS and serves as central point for several Point Of Sale devices.</p> <p>This system worked just fine for very large amount of entities, up to millions at a time. </p> <p>It basically works by determining which columns are required from the entity metadata, extracting it to a projection and executing a query with a result transformer.</p> <p>I'm not sure what changed, but I've encountered a situation where I'm seeing a memory leak of the transformed results, where the profiler tells me that the entities are being held in some List in the class Loader in the method DoQuery. I can't find anything in that method that would cause them to be held. </p> <p>Here is the function I'm using to get the row values, and it is also used for loading other normal NHibernate entities that I have:</p> <pre><code> 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; } </code></pre> <p>Here is the transformer that I'm using to convert from raw values to a dictionary with property names and values:</p> <pre><code>class EntityRetrieverResultTransform : IResultTransformer { public object TransformTuple(object[] tuple, string[] aliases) { EntityFields fields = new EntityFields(); for (int i = 0; i &lt; tuple.Length; i++) { string aliasName = aliases[i].Replace("[","").Replace("]",""); fields.Add(aliasName,tuple[i]); } return fields; } public IList TransformList(IList collection) { return collection; } } </code></pre> <p>the class EntityFields is a simple class:</p> <pre><code>public class EntityFields : Dictionary&lt;string,object&gt; { } </code></pre> <p>Here is a root graph from the profiler for a specific instance of the class EntityFields:</p> <p><img src="https://i.stack.imgur.com/U9ukC.png" alt="Root graph"> <a href="https://i.stack.imgur.com/U9ukC.png" rel="nofollow noreferrer">http://i.stack.imgur.com/U9ukC.png</a></p> <p>As you can see between DoQuery and List, there's no field name.</p> <p>At first I thought that the problem was with the result transformer, but even after taking that off, I still saw a memory leak of the raw values as string[].</p> <p>What am I doing wrong? Why are the EntityFields instances being held in the session?</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload