John Landheer
John Landheer

Reputation: 4019

Entity framework memory not released

I'm using a very simple asp.net mvc application with Entity Framework 6.0.2, .Net 4.5.1:

public class HomeController : Controller
{
   public ActionResult Index()
   {
      int count;
      using (var db = new LocalContext())
      {
         count = db.Counters.Count();
      }
      return View(count);
   }
}

public class Counter
{
   public int Id { get; set; }
}

public class LocalContext : DbContext
{
   public DbSet<Counter> Counters { get; set; }
}

If I do a load test on it, I eventually get an Out Of Memory Exception. (tinyget -srv:localhost -port:<port> -uri:/home/index/ -threads:30 -loop:5000). In Performance monitor I see the generation 2 Heap steadily grow. If I use a smaller loop value (say 500), the size grows until tinyget stops. Then the heap size stays the same (for at least 20 minutes, after that I stopped the server).

What am I doing wrong?

EDIT

So I tried Simon Mouriers suggestion and left out the EF code. Then I don't have memory problems. So I thought, maybe if I use Release instead of Debug, it will make a difference. And it did! Memory was released after a while and I could put high load on the site. Then I switched back to Debug to see if I could get more info and... even in Debug mode no problems anymore. FML, I worked a day on it and now I can't reproduce it anymore.

Upvotes: 20

Views: 13228

Answers (4)

J&#252;rgen Steinblock
J&#252;rgen Steinblock

Reputation: 31743

I don't see anything wrong with your code. Maybe this could be an issue with the underlying ADO.NET provider. Which database are you using?

I remember having issues with some unit test that did not release SQLite database files which I eventually solved with this code (in my DbContext class)

public class LocalContext : DbContext
{
    protected override void Dispose(bool disposing)
    {
        var connection = this.Database.Connection;
        base.Dispose(disposing);
        connection.Dispose();
    }
}

May be unrelated but I would give it a try.

Upvotes: 1

Jonathan Pick
Jonathan Pick

Reputation: 81

I would go for creating a class connection to the DB ..

public class DBconnection : IDisposable
{
    private ChatEntities _db = new ChatEntities();

    protected ChatEntities Db {
        get { return _db; }
    }

    public void Dispose()
    {
        if (_db != null)
        {
            _db.Dispose();
        }
    }
}

Then when you would like to connect and manipulate .. Lets call it the DBlogic class ..

public class DBlogic : DBconnection
{
       internal void WriteToDB(String str){
          //Do something ...

          Db.SaveChanges();
        }
}

This will eventually cause the Dispose to empty resources.. plus its cleaner .. at least for my eyes :D

Upvotes: 0

Anthony Mason
Anthony Mason

Reputation: 175

In your case the internally managed class that inherits from DbContext would then need to implement IDisposable and inside of the LocalContext add the following:

public void Dispose()
{
    this.Dispose(true);
    GC.SuppressFinalize(this);
}

protected virtual void Dispose(bool disposing)
{
     if (disposing)
     {
        // Manage any native resources.
     }
   //Handle any other cleanup.
}

Without specifically overriding the call to dispose, the using statement is only going to call Dispose() against the base class, while you need to dispose of the parent and base.

Upvotes: 3

Florin V
Florin V

Reputation: 344

This might not be the correct answer, but i suggest to keep your context managed by a IoC container. And add it with TrasientScope, or PerHttpRequest scope(example not provided due to a large varierty of ioc container syntax). If you want a specfic example, please reply for what DI you want

Upvotes: 0

Related Questions