强制刷新方法后累积内存

时间:2019-01-23 07:51:32

标签: c# entity-framework linq bootstrapper

我有一个连接到某些数据库的应用程序。首次执行后,该应用需要300Mb(一些数据正在从数据库中加载),并且可以。但是,在按下“刷新”按钮后,调用了刷新方法,在该方法中,我用新集合重新分配了旧集合,问题是它们在加载新数据后-旧数据仍在占用内存,因此在进行一些强制刷新之后,它可能占用2Gb。

我尝试用不同的选项来强制GC-什么也没发生。 GC认为我的收藏集不需要完全更新,而旧数据必须销毁。

我决定创建自己的Disposable集合,该集合继承自List或Collection并实现IDisposable [1]。然后,我抛出了所有类,这些类都包含在此类集合中,并且也实现了IDisposable(带有和不带有析构函数)。

我曾经使用过using()构造来清除那些集合[2],但是结果是集合已经变空了,但是仍然占用了内存。

使用配置文件程序,我看到每次刷新时Gen0对象的数量都会增加。刷新10次后,有120至580个此类对象,GC无法清除。

编辑:

  1. DataContext。
  2. UnitOfWork。
  3. 重新建立。
  4. 存储库注册和存储库服务
  5. 用于获取数据的服务方法。
  6. 使用Bootstrapper声明服务并使用它获取数据。

因此8处于“刷新”方法,并且每次刷新时都会重新分配数据。

[1]

    public class DisposableList<T> : List<T>, IDisposable where T : 
IDisposable
{
    public DisposableList()
    {

    }

    public DisposableList(T instance)
    {
        Add(instance);
    }

    public DisposableList(IEnumerable<T> instances)
    {
        AddRange(instances);
    }

    protected virtual void Dispose(bool disposing)
    {
        if (disposing)
        {
            foreach (T item in this)
            {
                item.Dispose();
            }
        }
    }
    public void Dispose()
    {
        Dispose(true);
    }

    ~DisposableList()
    {

    }
}

[2]

using (Resources = new DisposableList<Resources>())
     {

     }

[3]

public partial class MyDataContext : DbContext, IMyDataContext
{
    static MyDataContext()
    {
        Database.SetInitializer<MyDataContext>(null);
    }

    public MyDataContext(string connectionString)
        : base(connectionString)
    {
        try
        {
            if (!Database.Exists())
            {
                throw new Exception($"Нет соединения с базой данных 
                                   {Database.Connection.Database}");
            }                
        }
        catch (Exception ex)
        {
            throw ex;
        }
     }

     public IDbSet<Table> Table { get; set; }
 }

[4]

public class UnitOfWork : IUnitOfWork
     {
        DbContext _dataContext;
        IRepository[] _repositories;
        readonly object _locked = new object();

public UnitOfWork(DbContext dataContext, params IRepository[] 
                                                    repositories)
    {
        _dataContext = dataContext;
        _repositories = repositories;

    EFContextHelper.SetContext(_repositories, dataContext);
  }   


 public virtual void SaveChanges()
  {
      try
      {
          lock (_locked)
            {
                _dataContext.SaveChanges();
            }
      }
      catch (DbUpdateConcurrencyException ex)
      {
          throw;
      }
      catch (Exception ex)
      {
          throw;
      }
  }

  public virtual bool HasChanges()
    => _dataContext.ChangeTracker.HasChanges();

  public virtual void Rollback()
  {
      lock (_locked)
      {
          foreach (DbEntityEntry entry in 
                   _dataContext.ChangeTracker.Entries())
          {
  switch (entry.State)
  {
     case EntityState.Detached: break;
     case EntityState.Unchanged: break;
     case EntityState.Added:
         entry.State = EntityState.Detached;
         break;
     case EntityState.Deleted:
         entry.State = EntityState.Unchanged;
         break;
     case EntityState.Modified:
        entry.CurrentValues.SetValues(entry.OriginalValues);
        entry.State = EntityState.Unchanged;
        break;
     default:
        throw new ArgumentOutOfRangeException();
  }

          }
       }
   }

#region IDispose

    bool _disposed;
    public virtual void Dispose()
    {
        if (_disposed) { return; }

        foreach (var repo in _repositories)
        {
            repo.Dispose();
        }

        _dataContext?.Dispose();
        _dataContext = null;

        _disposed = true;
    }  

[5]

public interface IRepository<TEntity> : IRepository where TEntity : class
{
    TEntity Create();
    void Delete(TEntity entity);
    void Delete(IEnumerable<TEntity> entities);
    void AddOrUpdate(TEntity entity);
    void Attach(TEntity entity);
    void Reload(TEntity entity);
    void Detach(TEntity entity);
}

[6]

builder.RegisterType<Service>().As<IService>();
builder.RegisterType<Repository>).As<Repository>;

[7]

GetData()
{    
   using (_UnitOfWorkFactory.Create(_repository))
    {
         var data = _repository.Get();
    }
}

[8]

var service = Bootstrapper.Container.Resolve<IService>();
var data = service.GetData();

因此,我需要我的应用使用这样的内存量,该内存量是在首次执行后使用的。我希望我的旧数据被销毁,新数据取代旧数据。

0 个答案:

没有答案