title: Entity framework uses a lot of memory
body: <p>Here is a image from the ANTS memory profiler. It seens that there are a lot of objects hold in memory. How can I find what I am doing wrong?</p>
  
  <p><img src="https://i.stack.imgur.com/If3jJ.jpg" alt="ANTS memory profiler"></p>
  
  <pre><code>**UPDATE**
  </code></pre>
  
  <p>Here is my repository classes:</p>
  
  <pre><code>public class Repository&lt;T&gt; : IRepository&lt;T&gt; where T : class, IDataEntity
      {
          ObjectContext _context;
          IObjectSet&lt;T&gt; _objectSet;
  
          readonly string _entitySetName;
          readonly string[] _keyNames;
  
          private ObjectContext Context
          {
              get
              {
                  if (_context == null)
                  {
                      _context = GetCurrentUnitOfWork&lt;EFUnitOfWork&gt;().Context;
                  }
                  return _context;
              }
          }
  
          private IObjectSet&lt;T&gt; ObjectSet
          {
              get
              {
                  if (_objectSet == null)
                  {
                      _objectSet = this.Context.CreateObjectSet&lt;T&gt;();
                  }
                  return _objectSet;
              }
          }
  
          public TUnitOfWork GetCurrentUnitOfWork&lt;TUnitOfWork&gt;() where TUnitOfWork : IUnitOfWork
          {
              return (TUnitOfWork)UnitOfWork.Current;
          }
  
          public virtual IEnumerable&lt;T&gt; GetQuery()
          {
              return ObjectSet;
          }
  
          public virtual IEnumerable&lt;T&gt; GetQuery(params Expression&lt;Func&lt;T, object&gt;&gt;[] includes)
          {
              return ObjectSet.IncludeMultiple(includes);
          }
  
          public virtual IEnumerable&lt;T&gt; GetQuery(
              IEnumerable&lt;Expression&lt;Func&lt;T, bool&gt;&gt;&gt; filters,
              Func&lt;IQueryable&lt;T&gt;, IOrderedQueryable&lt;T&gt;&gt; orderBy,
              IEnumerable&lt;Expression&lt;Func&lt;T, object&gt;&gt;&gt; includes)
          {
              IQueryable&lt;T&gt; _query = ObjectSet;
  
              if (filters != null)
              {
                  foreach (var filter in filters)
                  {
                      _query = _query.Where(filter);
                  }
              }
  
              if (includes != null &amp;&amp; includes.Count() &gt; 0)
              {
                  _query = _query.IncludeMultiple(includes.ToArray());
              }
  
              if (orderBy != null)
              {
                  _query = orderBy(_query);
              }
  
              return _query;
          }
  
          public virtual IPaged&lt;T&gt; GetQuery(
              IEnumerable&lt;Expression&lt;Func&lt;T, bool&gt;&gt;&gt; filters,
              Func&lt;IQueryable&lt;T&gt;, IOrderedQueryable&lt;T&gt;&gt; orderBy,
              int pageNumber, int pageSize,
              IEnumerable&lt;Expression&lt;Func&lt;T, object&gt;&gt;&gt; includes)
          {
              IQueryable&lt;T&gt; _query = ObjectSet;
  
              if (filters != null)
              {
                  foreach (var filter in filters)
                  {
                      _query = _query.Where(filter);
                  }
              }
  
              if (orderBy != null)
              {
                  _query = orderBy(_query);
              }
  
              IPaged&lt;T&gt; page = new Paged&lt;T&gt;(_query, pageNumber, pageSize, includes);
  
              return page;
          }
  
          public virtual void Insert(T entity)
          {
              this.ObjectSet.AddObject(entity);
          }
  
          public virtual void Delete(T entity)
          {
              if (entity is ISoftDeletable)
              {
                  ((ISoftDeletable)entity).IsDeleted = true;
                  //Update(entity);
              }
              else
              {
                  this.ObjectSet.DeleteObject(entity);
              }
          }
  
          public virtual void Attach(T entity)
          {
              ObjectStateEntry entry = null;
              if (this.Context.ObjectStateManager.TryGetObjectStateEntry(entity, out entry) == false)
              {
                  this.ObjectSet.Attach(entity);
              }
          }
  
          public virtual void Detach(T entity)
          {
              ObjectStateEntry entry = null;
              if (this.Context.ObjectStateManager.TryGetObjectStateEntry(entity, out entry) == true)
              {
                  this.ObjectSet.Detach(entity);
              }
          }
      }
  </code></pre>
  
  <p>Now, if I have class A that holds records from table A, I also create class:</p>
  
  <pre><code>public class ARepository:BaseRepository&lt;A&gt; {
  // Implementation of A's queries and specific db operations
  }
  </code></pre>
  
  <p>Here is my EFUnitOfWork class:</p>
  
  <pre><code>public class EFUnitOfWork : IUnitOfWork, IDisposable
  {
      public ObjectContext Context { get; private set; }
  
      public EFUnitOfWork(ObjectContext context)
      {
          Context = context;
          context.ContextOptions.LazyLoadingEnabled = true;
      }
  
      public void Commit()
      {
          Context.SaveChanges();
      }
  
      public void Dispose()
      {
          if (Context != null)
          {
              Context.Dispose();
          }
          GC.SuppressFinalize(this);
      }
  }
  </code></pre>
  
  <p>And UnitOfWork class:</p>
  
  <pre><code>public static class UnitOfWork
  {
      private const string HTTPCONTEXTKEY = "MyProj.Domain.Business.Repository.HttpContext.Key";
  
      private static IUnitOfWorkFactory _unitOfWorkFactory;
      private static readonly Hashtable _threads = new Hashtable();
  
      public static void Commit()
      {
          IUnitOfWork unitOfWork = GetUnitOfWork();
          if (unitOfWork != null)
          {
              unitOfWork.Commit();
          }
      }
  
      public static IUnitOfWork Current 
      {
          get
          {
              IUnitOfWork unitOfWork = GetUnitOfWork();
              if (unitOfWork == null)
              {
                  _unitOfWorkFactory = ObjectFactory.GetInstance&lt;IUnitOfWorkFactory&gt;();
                  unitOfWork = _unitOfWorkFactory.Create();
                  SaveUnitOfWork(unitOfWork);
              }
              return unitOfWork;
          }
      }
  
      private static IUnitOfWork GetUnitOfWork()
      {
          if (HttpContext.Current != null)
          {
              if (HttpContext.Current.Items.Contains(HTTPCONTEXTKEY))
              {
                  return (IUnitOfWork)HttpContext.Current.Items[HTTPCONTEXTKEY];
              }
              return null;
          }
          else
          {
              Thread thread = Thread.CurrentThread;
              if (string.IsNullOrEmpty(thread.Name))
              {
                  thread.Name = Guid.NewGuid().ToString();
                  return null;
              }
              else
              {
                  lock (_threads.SyncRoot)
                  {
                      return (IUnitOfWork)_threads[Thread.CurrentThread.Name];
                  }
              }
          }
      }
  
      private static void SaveUnitOfWork(IUnitOfWork unitOfWork)
      {
          if (HttpContext.Current != null)
          {
              HttpContext.Current.Items[HTTPCONTEXTKEY] = unitOfWork;
          }
          else
          {
              lock(_threads.SyncRoot)
              {
                  _threads[Thread.CurrentThread.Name] = unitOfWork;
              }
          }
      }
  }
  </code></pre>
  
  <p>Here is how I use this:</p>
  
  <pre><code> public class TaskPriceRepository : BaseRepository&lt;TaskPrice&gt;
      {
          public void Set(TaskPrice entity)
          {
              TaskPrice taskPrice = GetQuery().SingleOrDefault(x =&gt; x.TaskId == entity.TaskId);
              if (taskPrice != null)
              {
                  CommonUtils.CopyObject&lt;TaskPrice&gt;(entity, ref taskPrice);
              }
              else
              {
                  this.Insert(entity);
              }
          }
      }
  
  public class BranchRepository : BaseRepository&lt;Branch&gt;
  {
      public IList&lt;Branch&gt; GetBranchesList(Guid companyId, long? branchId, string branchName)
      {
          return Repository.GetQuery().
              Where(b =&gt; companyId == b.CompanyId).
              Where(b =&gt; b.IsDeleted == false).
              Where(b =&gt; !branchId.HasValue || b.BranchId.Equals(branchId.Value)).
              Where(b =&gt; branchName == null || b.BranchName.Contains(branchName)).
              ToList();
      }
  }
  
  [WebMethod]
  public void SetTaskPrice(TaskPriceDTO taskPrice)
  {
      TaskPrice tp = taskPrice.ToEntity();
      TaskPriceRepository rep = new TaskPriceRepository();
      rep.Set(tp);
      UnitOfWork.Commit();
  }
  
  [WebMethod]
  public IList&lt;Branch&gt; GetBranchesList()
  {
      BranchRepository rep = new BranchRepository();
      return rep.GetBranchesList(m_User.UserCompany.CompanyId, null, null).ToList();
  }
  </code></pre>
  
  <p>I hope this is enough info to help me solving the problem. Thanks.</p>
  
  <p><strong><code>UPDATE 2</code></strong><br>
  There is also UnitOfWorkFactory that initializes UnitOfWork:</p>
  
  <pre><code>public class UnitOfWorkFactory : IUnitOfWorkFactory
  {
      private static Func&lt;ObjectContext&gt; _objectContextDelegate;
      private static readonly Object _lockObject = new object();
  
      public static void SetObjectContext(Func&lt;ObjectContext&gt; objectContextDelegate)
      {
          _objectContextDelegate = objectContextDelegate;
      }
  
      public IUnitOfWork Create()
      {
          ObjectContext context;
          lock (_lockObject)
          {
               context = _objectContextDelegate();
          }
          return new EFUnitOfWork(context);
      }
  }
  </code></pre>
  
  <p>In order to use this, in the application startup I use structuremap:</p>
  
  <pre><code>  ObjectFactory.Initialize(x =&gt;
          {
              x.For&lt;IUnitOfWorkFactory&gt;().Use&lt;UnitOfWorkFactory&gt;();
              x.For(typeof(IRepository&lt;&gt;)).Use(typeof(Repository&lt;&gt;));
          });
  </code></pre>